返回

Java 11 迁移 IIOP Corba "no permission" 权限问题解决

java

Java 11 迁移: 解决 IIOP Corba “no permission” 权限问题

在把客户端代码从 Java 8 迁移到 Java 11 时,如果服务器端使用 IIOP Corba 进行通讯,可能会遇到 “Corba no permission” 权限问题。这个问题即使在 Java 8 客户端与 Java 11 服务器端通讯时也无法通过。

这种错误的原因不是单一的,而是多因素共同导致的。主要问题在于从 Java 8 到 Java 11 版本迁移过程中,Java EE 模块被移除。 加上旧有的javax function的更新变动以及与一些库冲突等等。接下来我们来看详细的原因及解决方案。

一、问题根源分析

1. Java EE 模块的移除

Java 11 不再包含 Java EE 模块。像 JAX-WS, JAXB, JNDI 这样的 API 不再随 JDK 捆绑提供。这对依赖这些 API 的 CORBA 客户端造成冲击。使用 java:global 等全局 JNDI 名称需要特别关注。

2. CORBA 安全性增强

Payara 5 和底层 GlassFish 对 CORBA 实施了更严格的安全策略。如果请求中没有有效的安全上下文,这些服务会拒绝操作。Java 8 中某些安全设定默认为宽松,可能不会报错;到了 Java 11 则会拦截。

3. 客户端配置不当

Java 11 的客户端可能缺少必要的属性配置或依赖包。例如正确指定 ORB 的初始类、端口,处理好安全相关上下文的初始化和管理。配置错误也可能会触发 “no permission”。

4. 依赖冲突

在添加 Java EE 模块的过程中,不正确处理不同版本间的兼容性会引入错误。

二、解决方案及步骤

针对不同的原因有多种方案可以解决此问题,一般采用自上而下层层递进的方式进行解决。具体包括:添加必需的依赖项、显式启用 IIOP 安全、正确配置认证信息。具体如下:

1. 添加必要的依赖

由于 Java 11 移除了 Java EE 相关模块,需要在客户端项目中显式引入相应的 JAR 包。例如 GlassFish CORBA ORB, JNDI 实现等。对于使用 Maven 管理项目的场景,可加入如下依赖:

<dependency>
    <groupId>org.glassfish.corba</groupId>
    <artifactId>glassfish-corba-orb</artifactId>
    <version>4.2.4</version> 
</dependency>
<dependency>
    <groupId>org.glassfish</groupId>
    <artifactId>javax.ejb</artifactId>
    <version>3.2.1</version>
</dependency>
<dependency>
    <groupId>org.glassfish.corba</groupId>
    <artifactId>glassfish-corba-omgapi</artifactId>
    <version>4.2.4</version>
</dependency>
<dependency>
    <groupId>jakarta.platform</groupId>
    <artifactId>jakarta.jakartaee-api</artifactId>
    <version>8.0.0</version>
    <scope>provided</scope>
</dependency>

<!-- gf-client 视情况是否引入 -->
<!--
<dependency>
  <groupId>org.glassfish.main.appclient</groupId>
  <artifactId>gf-client</artifactId>
  <version>5.1.0</version> 
</dependency>
-->

特别提示:如果通过 <scope>provided</scope>添加相关依赖时需要考虑实际运行时的依赖传递问题。

2. 调整JNDI查找
尝试使用非全局 JNDI 名称,使用 corbaname RIR (Resolvable Initial Reference) 格式,代码改动可以参考下面的方式:

// 原有 Java 11 测试代码的 JNDI 部分
String jndiName = "java:global/Portal/Portalejb/PortalService!se.services.portal.PortalServiceHome";

// 修改为以下内容
String jndiName = "corbaname:iiop:localhost:3700#Portal/Portalejb/PortalService";

这种方式将不依赖服务器端返回的Initial Reference列表进行解析。

3. 明确启用 IIOP 安全性 (针对有认证需求的场景)

如果服务器端要求进行身份验证,而之前的配置并没有使用安全性设置,需要在代码中添加以下部分:

(1) 在客户端代码中,初始化InitialContext 前加入安全性属性:

Properties props = new Properties();
// ... 其他属性设置 ...
props.setProperty(Context.SECURITY_PRINCIPAL, "username"); // 替换为实际的用户名
props.setProperty(Context.SECURITY_CREDENTIALS, "password"); // 替换为实际的密码

// ... 使用 props 创建 InitialContext ...

这一步骤可以简单配置安全凭证。但无法正确建立安全上下文。

(2) 配置 ORB SSL 参数

//服务端
//<iiop-listener address="0.0.0.0" port="3700" id="orb-listener-1" security-enabled="true">
//  <property name="keyfile" value="/config/ssl_certificate.pfx"></property>
//  <property name="keypass" value="sslPassword"></property>
//</iiop-listener>
    
//客户端
props.put("org.omg.CORBA.ORBClass", "com.sun.corba.ee.impl.orb.ORBImpl");
props.put("com.sun.CORBA.giop.ORBGIOPVersion", "1.2");
props.put("com.sun.CORBA.transport.ORBTCPReadTimeouts", "500:60000:100:20");
props.put("javax.net.ssl.keyStore", "cacerts.jks");//替换为真实地址
props.put("javax.net.ssl.keyStorePassword", "changeit");//替换为正确密码
props.put("javax.net.ssl.trustStore", "cacerts.jks");//替换为真实地址
props.put("javax.net.ssl.trustStorePassword", "changeit");//替换为正确密码

props.put("com.sun.CORBA.ORBIiopSSLClientPort", "3700");//使用SSL安全链接

props.setProperty("com.sun.corba.ee.transport.ORBWaitForResponseTimeout", "5000");

这套配置能够实现客户端安全连接到远端。

(3)如果安全仍然报错

检查客户端的 truststore。
查看日志确认失败原因是否与服务端不信任客户端证书有关。如果相关,应在服务端配置相应的客户端证书以信任访问客户端。

通过以上方式基本可以解决客户端的链接访问问题。如果依然出现其他错误,请查看服务器端更详细的日志并检查客户端的环境进行调整。需要结合错误堆栈的详情来进行调试。

希望这个方案能帮你在解决 “no permission” 问题的路途上前进一大步。安全方面一定不要松懈!细致地排查、谨慎的配置方是王道。 在处理好连接安全相关配置的同时不要忘了关注通讯性能上的配置是否合理。这包括 TCP 超时时间的配置。IIOP线程池相关的优化也可以作为后继步骤。