1

我正在从 JBoss 5.0.1 迁移到 JBoss 7.2。

我正在使用远程 EJB 客户端调用 EJB。我必须迁移一个从AbstractServerLoginModule.

我设法配置了 JBoss,以便实际调用自定义登录模块。

在自定义登录模块中,我实现了一个javax.security.auth.callback.NameCallback和一个javax.security.auth.callback.ObjectCallback类似的:

NameCallback ncb = new NameCallback("Username:");
PasswordCallback pcb = new PasswordCallback("Password:", false);
try
{
    callbackHandler.handle(new Callback[] { ncb, pcb });
}
catch (Exception e)
{
    if (e instanceof RuntimeException)
    {
        throw (RuntimeException) e;
    }
    return false; 
}
String name = ncb.getName();
String pwd = new String(pcb.getPassword());

我看到用户按照我的预期传递给NameCallback.

但我观察到传递给的密码PasswordCallback始终是“随机值”,如“0299df2c-620a-4ac6-83d3-50daaa65fb90”。

我用来调用服务器的客户端代码如下所示:

Properties clientProp = new Properties();
clientProp.put("remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED", "false");
clientProp.put("remote.connections", "default");
clientProp.put("remote.connection.default.port", "4447");
clientProp.put("remote.connection.default.host", "localhost");
clientProp.put("remote.connection.default.username", "USER");
clientProp.put("remote.connection.default.password", "PASSWORD");
clientProp.put("remote.connection.default.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS", "false");
clientProp.put("remote.connection.default.connect.options.org.xnio.Options.SASL_POLICY_NOPLAINTEXT", "false");

EJBClientConfiguration cc = new PropertiesBasedEJBClientConfiguration(clientProp);
ContextSelector<EJBClientContext> selector = new ConfigBasedEJBClientContextSelector(cc);
EJBClientContext.setSelector(selector);

final Properties jndiProperties = new Properties();
jndiProperties.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
jndiProperties.put("jboss.naming.client.ejb.context", true);
jndiProperties.put(InitialContext.SECURITY_PRINCIPAL, "USER");
jndiProperties.put(InitialContext.SECURITY_CREDENTIALS, "PASSWORD");

我希望密码以纯文本形式到达自定义登录模块中的服务器上。那可能吗?我怎样才能做到这一点?

4

1 回答 1

3

我终于解决了这个问题。

密码设置为随机值的原因是密码从未到达服务器。如果没有传递密码,JBoss 中的安全实现似乎会将密码设置为随机值。

使用以下客户端代码,密码按预期以明文形式出现在登录模块中:

final Properties jndiProperties = new Properties();

jndiProperties.put("remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED", "false");

jndiProperties.put("remote.connections", "one");
jndiProperties.put("remote.connection.one.port", "4447");
jndiProperties.put("remote.connection.one.host", "localhost");

jndiProperties.put("remote.connection.one.connect.options.org.xnio.Options.SASL_POLICY_NOPLAINTEXT", "false");
jndiProperties.put("remote.connection.one.connect.options.org.xnio.Options.SASL_DISALLOWED_MECHANISMS", "JBOSS-LOCAL-USER");

jndiProperties.put("remote.clusters", "ejb");
jndiProperties.put("remote.cluster.ejb.connect.options.org.xnio.Options.SASL_POLICY_NOPLAINTEXT", "false");

jndiProperties.put("remote.connection.one.username", username);
jndiProperties.put("remote.connection.one.password",password);
jndiProperties.put("remote.cluster.ejb.username", username);
jndiProperties.put("remote.cluster.ejb.password", password);

jndiProperties.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");

EJBClientConfiguration cc = new PropertiesBasedEJBClientConfiguration(jndiProperties);
ContextSelector<EJBClientContext> selector = new ConfigBasedEJBClientContextSelector(cc);
EJBClientContext.setSelector(selector);

final Context context = new InitialContext(jndiProperties);

MessageServieRemote msgService = (MessageServieRemote) context.lookup("ejb:TestEar/TestNopEjb//MessageService!net.jonasbandi.ejbremote.MessageServieRemote");
System.out.println(msgService.getMessage());

重要的部分似乎是以下两个属性:

jndiProperties.put("remote.connection.one.connect.options.org.xnio.Options.SASL_POLICY_NOPLAIN  TEXT", "false");
jndiProperties.put("remote.connection.one.connect.options.org.xnio.Options.SASL_DISALLOWED_MECHANISMS", "JBOSS-LOCAL-USER");

上述第一个属性确保密码以明文形式从客户端传递到服务器。

当您在同一台机器上运行 JBoss 和 EJB 客户端时,EJB 客户端会优化通信并“本地”调用服务器,而不是过度远程处理。在我的情况下,这绕过了在远程子系统引用的 ApplicationRealm 上配置的登录模块。上述第二个属性不允许这种行为,并强制 EJB 客户端始终使用远程处理,因此不绕过我的自定义登录模块。

只是为了完成:服务器配置的相关部分(在我的情况下在文件中standalone-ha.xml)如下所示:

远程子系统引用 AppplicationRealm:

<subsystem xmlns="urn:jboss:domain:remoting:1.1">
    <connector name="remoting-connector" socket-binding="remoting" security-realm="ApplicationRealm"/>
</subsystem>

ApplicationRealm 引用自定义安全域

       <security-realm name="ApplicationRealm">
            <authentication>
                <jaas name="myDomain"/>
            </authentication>
            <authorization>
                <properties path="application-roles.properties" relative-to="jboss.server.config.dir"/>
            </authorization>
        </security-realm>

自定义安全域配置自定义登录模块:

            <security-domain name="myDomain" cache-type="default">
                <authentication>
                    <login-module code="net.jonasbandi.ejbremote.CustomLoginModule" flag="required " module="deployment.TestEar.ear">
                        <module-option name="password-stacking" value="useFirstPass"/>
                        <module-option name="realm" value="ApplicationRealm"/>
                    </login-module>
                </authentication>
            </security-domain>

请注意,在上述情况下,我将 CustomLoginModule 部署为 EAR 的一部分,因此该属性module="deployment.TestEar.ear"是必需的。

最后,我将默认安全域设置为我的自定义安全域:

<default-security-domain value="myDomain"/>
于 2013-08-21T21:19:39.003 回答