JBoss7:自定义登录模块无法正常工作 [英] JBoss7: Custom Login Module not working

查看:177
本文介绍了JBoss7:自定义登录模块无法正常工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在从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(例外e)
{
if(e instanceof RuntimeException)
{
throw(RuntimeException)e;
}
返回false;
}
String name = ncb.getName();
String pwd = new String(pcb.getPassword());

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



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



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

 属性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属性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);

我希望密码以自定义登录模块中的服务器上的纯文本形式到达。那可能吗?我怎么能实现呢?

解决方案

我终于解决了这个问题。



<密码设置为随机值的原因是密码永远不会到达服务器。似乎JBoss中的安全实现然后在没有密码传递的情况下将密码设置为随机值。



使用以下客户端代码,密码在纯文本中按预期显示登录模块:

  final属性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,密码);
jndiProperties.put(remote.cluster.ejb.username,username);
jndiProperties.put(remote.cluster.ejb.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客户机优化通信并本机调用服务器而不是远程远程调用服务器。在我的例子中,这绕过了由remotinng子系统引用的ApplicationRealm上配置的login-module。上述第二个属性不允许此行为并强制EJB客户端始终使用远程处理,因此不会绕过我的自定义登录模块。



仅用于完成:相关部分服务器配置(在我的情况下在文件 standalone-ha.xml 中)看起来像这样:



远程处理子系统参考AppplicationRealm:

 < subsystem xmlns =urn:jboss:domain:remoting:1.1> 
< connector name =remoting-connectorsocket-binding =remotingsecurity-realm =ApplicationRealm/>
< / subsystem>

ApplicationRealm引用自定义安全域

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

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

 < security-domain name =myDomaincache-type =default> 
< authentication>
< login-module code =net.jonasbandi.ejbremote.CustomLoginModuleflag =requiredmodule =deployment.TestEar.ear>
< module-option name =password-stackingvalue =useFirstPass/>
< module-option name =realmvalue =ApplicationRealm/>
< / login-module>
< / authentication>
< / security-domain>

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



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

 < default-security-domain value =myDomain/> 


I am in the process of migrating from JBoss 5.0.1 to JBoss 7.2.

I am calling EJBs with a remote EJB client. I have to migrate a custom login module that derives from AbstractServerLoginModule.

I managed to configure JBoss so that the custom login module is actually called.

In the custom login module I implement a javax.security.auth.callback.NameCallback and a javax.security.auth.callback.ObjectCallback like that:

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());

I see that the user is passed as I expect it to the NameCallback.

But I observe that the password that is passed to the PasswordCallback is always a "random value" like "0299df2c-620a-4ac6-83d3-50daaa65fb90".

The client code I use to call the server looks like this:

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");

I would like that the password arrives in plain text on the server in the custom login module. Is that possible? How can I achieve that?

解决方案

I finally solved the problem.

The reason why the password was set to a random value was that the password never arrived at the server. It seems that the security implementation in JBoss then sets the password to a random value if no password is passed.

With the following client code the password appeared as expected in plaintext in the login module:

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());

The important parts seem to be the following two properties:

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");

The first of the above properties ensures that the password is passed in plaintext from the client to the server.

When you are running JBoss and the EJB client on the same machine, then the EJB client optimizes communication and calls the server "natively" and not over remoting. In my case this bypasses the login-module which is configured on the ApplicationRealm which is referenced by the remotinng subsystem. The second of the above properties disallows this behavior and forces the EJB client always to use remoting and therefore not to bypass my custom login module.

Just for completion: The relevant parts of the server configuration (in my case in the file standalone-ha.xml) look like this:

Remoting subsystem references AppplicationRealm:

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

ApplicationRealm references custom security domain

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

Custom security domain configures custom login module:

            <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>

Note in the above case I deploy the CustomLoginModule as part of my EAR, therefore the attribute module="deployment.TestEar.ear" is necessary.

And finaly I set the default security domain to my custom security domain:

<default-security-domain value="myDomain"/>

这篇关于JBoss7:自定义登录模块无法正常工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆