0

我已经在我的 JBoss (4.2.2.GA) 服务器和我们的 J2SE 客户端之间建立了 JMS 连接。客户端通过 Java Web Start 运行,在 JNLP 中,我有以下内容:

<jnlp version="1.5+" codebase="$$codebase" href="start.jnlp">
    <!-- Information -->
    <security>
        <all-permissions />
    </security>
    <resources>
        <!-- Some other non-JMS resources -->
        <jar href="concurrent.jar" />
        <jar href="jboss-common.jar" />
        <jar href="jboss-j2ee.jar" />
        <jar href="jbossmq.jar" />
        <jar href="jnpserver.jar" />
        <jar href="log4j.jar" />
    <resources>
</jnlp>

JMS 连接工作正常。我已经成功配置、订阅和测试了一个 JMS 主题。这是该代码:

final String topic = ... ;
final InitialContext context = new InitialContext();
PrivilegedAction<JmsConnectionContext> action = new PrivilegedAction<JmsConnectionContext>() {

    @Override
    public JmsConnectionContext run() {
        try {
            TopicConnectionFactory connectionFactory = (TopicConnectionFactory) context.lookup("TopicConnectionFactory");
            TopicConnection topicConnection = connectionFactory.createTopicConnection();
            int sessionId = Client.getSession().getSessionId();
            topicConnection.setClientID("UMClient-" + sessionId);
            TopicSession session = topicConnection.createTopicSession(false,
                    TopicSession.AUTO_ACKNOWLEDGE);

            Topic jmsTopic = (Topic) context.lookup(topic);
            TopicSubscriber subscriber = session.createDurableSubscriber(jmsTopic, topic + "-" +
                    sessionId);
            subscriber.setMessageListener(new JmsTopicMessageListener());
            topicConnection.start();
            return new JmsConnectionContext(topic, topicConnection, session);
        } catch(Exception e) {
            logger.log(Level.SEVERE, "Topic creation and connection failed.", e);
            return null;
        }
    }
};
return AccessController.doPrivileged(action);

而且我的 JNDI 属性配置非常简单:

java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
java.naming.factory.url.pkgs=org.jboss.naming
java.naming.provider.url=10.1.3.143:1099

此外,这些罐子都使用我们的公司证书进行了签名,该证书是通过 CA 颁发的(将在接下来的几个月内到期,但仍然有效)。我还尝试清除javaws缓存以确保它不是过时的代码问题。

那么为什么警告仍然出现?我将它作为特权操作运行,据我所知,它应该只授予代码all-permissions来自 JNLP 文件的策略,但是当sun.rmi.transport.tcp.TCPChannel.checkConnectPermission()在 JNDI 查找期间被调用时,JWS 安全管理器会显示安全警告。为了让 JNDI 查找具有提升的连接权限,我还需要配置其他东西吗?我可以通过 Java Web Start 进行配置吗?

更新

我还在处理这个问题。当它尝试访问服务器上的 RMI 端口时,我将对话框缩小到出现(它正在检查权限host:1098)。我尝试将java.rmi.server.hostname属性设置为,不使用此错误报告host中列出的解决方法。由于第一次 RMI 查找直到客户端已经启动之后才会发生,我假设我不需要找到一种方法来通过.<property>

这是我在安全警告中单击“取消”时的堆栈跟踪:

java.security.AccessControlException: access denied (java.net.SocketPermission 10.1.3.143:1098 connect,resolve)
    at java.security.AccessControlContext.checkPermission(Unknown Source)
    at java.security.AccessController.checkPermission(Unknown Source)
    at java.lang.SecurityManager.checkPermission(Unknown Source)
    at java.lang.SecurityManager.checkConnect(Unknown Source)
    at com.sun.javaws.security.JavaWebStartSecurity.checkConnect(Unknown Source)
    at sun.rmi.transport.tcp.TCPChannel.checkConnectPermission(Unknown Source)
    at sun.rmi.transport.tcp.TCPChannel.newConnection(Unknown Source)
    at sun.rmi.server.UnicastRef.invoke(Unknown Source)
    at org.jnp.server.NamingServer_Stub.lookup(Unknown Source)
    at org.jnp.interfaces.NamingContext.lookup(NamingContext.java:667)
    at org.jnp.interfaces.NamingContext.lookup(NamingContext.java:627)
    at javax.naming.InitialContext.lookup(Unknown Source)
    at org.jboss.naming.LinkRefPairObjectFactory.getObjectInstance(LinkRefPairObjectFactory.java:85)
    at javax.naming.spi.NamingManager.getObjectInstance(Unknown Source)
    at org.jnp.interfaces.NamingContext.getObjectInstance(NamingContext.java:1273)
    at org.jnp.interfaces.NamingContext.getObjectInstanceWrapFailure(NamingContext.java:1290)
    at org.jnp.interfaces.NamingContext.getObjectInstanceWrapFailure(NamingContext.java:1298)
    at org.jnp.interfaces.NamingContext.lookup(NamingContext.java:763)
    at org.jnp.interfaces.NamingContext.lookup(NamingContext.java:627)
    at javax.naming.InitialContext.lookup(Unknown Source)
    at com.ultramain.uui.jms.JmsHelper.jndiLookup(JmsHelper.java:145)
    ...

所以问题是特定于 RMI 访问的。为什么设置主机名不能修复对话框,正如链接的错误报告中的解决方法和我找到的其他一些资源中所建议的那样?有没有其他解决方法来解决这个问题?

4

1 回答 1

0

解决方案是一个大黑客,但这是我能找到的。

从这里的信息来看,JWS 安全管理器没有将 RMI 代码列为受信任代码,因为它是在单独的类加载器下加载的。因为代码并非源自 JNLP,所以 JWS 不允许它以all-permissions安全方式运行。

对此的 hacky 修复只是简单地用以下内容包装每个查找:

Topic topic = null;
SecurityManager prevSecurityManager = System.getSecurityManager();
try {
    System.setSecurityManager(null);
    topic = (Topic) context.lookup(name);
} finally {
    System.setSecurityManager(prevSecurityManager);
}

将 设置SecurityManagernull绕过 JWS 安全管理器,让默认的安全管理器接管。

最终,我想找到一种方法将 RMI 代码添加到 JNLP 的可信代码库中,但这个解决方案将在我们的开发环境和演示中工作,直到我能做到为止。这不是一种非常安全的做事方式,尤其是在像这样可以是多线程的应用程序中。它提供了一个没有安全管理器的小机会窗口,因此如果有人有一个解决方案可以让我信任 JNLP 配置中的 RMI 代码,请发布它并且您的答案将被接受(前提是它当然有效)。

于 2013-07-26T23:36:57.733 回答