jboss eap 7.0_创建委托登录模块(用于JBoss EAP 6.1)

jboss eap 7.0

[如果只想查看代码,请向下滚动]

动机

RHQ中,我们需要一个安全域,该域可用于通过容器管理的安全性来保护REST-api及其Web应用程序。 过去,我只是使用经典的DatabaseServerLoginModuleDatabaseServerLoginModule进行身份验证。 现在RHQ还允许将用户放在LDAP目录中,而上述模块未涵盖这些目录。 我有两个选择开始:

  • 将LDAP登录模块复制到REST的安全域中
  • 将安全域用于已经用于UI和CLI的REST-api

后一种选择当然有利于防止代码重复,所以我走了那条路。 并失败了。

我失败了,因为RHQ在启动时删除并重新创建了安全域,而服务器正在检测到该错误,并抱怨从rhq-rest.war引用的安全域突然消失了。

因此,下一个尝试:不要在启动时重新创建域,而只添加/删除ldap-login模块(我说的是模块,因为实际上我们需要两个)。

这也没有按预期工作:

  • 基础AS有时会进入需要重新加载的模式,并且未应用更改
  • 除去ldap模块后,仍会缓存它们中的主体
  • 刷新缓存无效,服务器进入需要重新加载的模式

因此,我现在要做的是为rest-security-domain实现一个登录模块,该模块仅委派给另一个进行身份验证,然后在成功时添加角色。

这样,rhq-rest.war便具有对该rest-security-domain的固定引用,而另一个安全域则可以像以前一样处理。

实作

让我们从standalone.xml文件中的片段开始,该片段描述安全域并参数化模块

<security-domain name="RHQRESTSecurityDomain" cache-type="default">
   <authentication>
     <login-module code="org.rhq.enterprise.server.core.jaas.DelegatingLoginModule" flag="sufficient">
       <module-option name="delegateTo" value="RHQUserSecurityDomain"/>
       <module-option name="roles" value="rest-user"/>
     </login-module>
   </authentication>
 </security-domain>

因此,此定义设置了一个安全域RHQRESTSecurityDomain ,该域使用我将在稍后描述的DelegatingLoginModule。 传递了两个参数:

  • proxyTo:用于验证用户身份的另一个域的名称
  • 角色:以逗号分隔的要添加到主体的模块列表(并且web.xml的security-constraint部分中需要这些模块)

对于代码,我没有显示完整清单。 你可以在git中找到它

为了使我们的生活更轻松,我们不是自己实现所有功能,而是扩展已经存在的UsernamePasswordLoginModule并仅覆盖某些方法。

public class DelegatingLoginModule extends UsernamePasswordLoginModule {

首先,我们使用传递的选项初始化模块,并使用我们委派给的域创建一个新的LoginContext:

@Override
    public void initialize(Subject subject, CallbackHandler callbackHandler, 
        Map<String, ?> sharedState,
        Map<String, ?> options) 
    {
        super.initialize(subject, callbackHandler, sharedState, options);

        /* This is the login context (=security domain) we want to delegate to */
        String delegateTo = (String) options.get("delegateTo");

		/* Now create the context for later use */
        try {
            loginContext = new LoginContext(delegateTo, new DelegateCallbackHandler());
        } catch (LoginException e) {
            log.warn("Initialize failed : " + e.getMessage());
        }

有趣的部分是login()方法,在该方法中我们获取用户名/密码并存储以供以后使用,然后我们尝试登录到委托域,如果成功,则告诉super我们成功了,以便它可以发挥作用。 。

@Override
    public boolean login() throws LoginException {
        try {
            // Get the username / password the user entred and save if for later use
            usernamePassword = super.getUsernameAndPassword();
            
            // Try to log in via the delegate
            loginContext.login();

            // login was success, so we can continue
            identity = createIdentity(usernamePassword[0]);
            useFirstPass=true;

            // This next flag is important. Without it the principal will not be
            // propagated
            loginOk = true;

这里需要loginOk标志,以便超类将调用LoginModule.commit()并选择主体和角色。

不将其设置为true将导致成功login()但没有附加主体。

if (debugEnabled) {
                log.debug("Login ok for " + usernamePassword[0]);
            }

            return true;
        } catch (Exception e) {
            if (debugEnabled) {
                LOG.debug("Login failed for : " + usernamePassword[0] + ": " + e.getMessage());
            }
            loginOk = false;
            return false;
        }
    }

成功后,super将调用以下两种方法来获取主体及其角色:

@Override
    protected Principal getIdentity() {
        return identity;
    }


    @Override
    protected Group[] getRoleSets() throws LoginException {

        SimpleGroup roles = new SimpleGroup("Roles");

        for (String role : rolesList ) {
            roles.addMember( new SimplePrincipal(role));
        }
        Group[] roleSets = { roles };
        return roleSets;
    }

现在,最后一部分是回调处理程序,我们委托的其他域将使用该回调处理程序从我们那里获取凭据。 它是经典的JAAS登录回调处理程序。 首先让我感到困惑的一件事是,该处理程序在登录期间被调用了几次,我认为这是错误的。 但是实际上,它被调用的次数与RHQUserSecurityDomain中配置的登录模块的数量相对应。

private class DelegateCallbackHandler implements CallbackHandler {
        @Override
        public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {

            for (Callback cb : callbacks) {
                if (cb instanceof NameCallback) {
                    NameCallback nc = (NameCallback) cb;
                    nc.setName(usernamePassword[0]);
                }
                else if (cb instanceof PasswordCallback) {
                    PasswordCallback pc = (PasswordCallback) cb;
                    pc.setPassword(usernamePassword[1].toCharArray());
                }
                else {
                    throw new UnsupportedCallbackException(cb,"Callback " + cb + " not supported");
                }
            }
        }
    }

同样,完整的代码在RHQ git仓库中可用。

调试(在EAP 6.1 alpha或更高版本中)

如果您编写了这样的登录模块,但该模块不起作用,则需要对其进行调试。 从通常的方法开始,以了解我的login()方法是否按预期工作,但登录失败。 我添加了打印语句等,以发现从未调用过getRoleSets()方法。 但是,一切仍然看起来还不错。 我进行了一些谷歌搜索,发现了这个不错的Wiki页面 。 可以告诉Web应用执行审核日志记录

<jboss-web>
    <context-root>rest</context-root>
    <security-domain>RHQRESTSecurityDomain</security-domain><disable-audit>false</disable-audit>

仅此标志是不够的,因为您还需要设置适当的记录器,这在Wiki页面上进行了说明。 启用此功能后,我看到了类似

16:33:33,918 TRACE [org.jboss.security.audit] (http-/0.0.0.0:7080-1) [Failure]Source=org.jboss.as.web.security.JBossWebRealm;
principal=null;request=[/rest:….

因此很明显,登录模块未设置主体。 查看超类中的代码,然后将我带到上面提到的loginOk标志。

现在,一切都正确设置了,自动日志看起来像

22:48:16,889 TRACE [org.jboss.security.audit] (http-/0.0.0.0:7080-1) [Success]Source=org.jboss.as.web.security.JBossWebRealm;Step=hasRole; principal=GenericPrincipal[rhqadmin(rest-user,)]; request=[/rest:cookies=null:headers=authorization=user-agent=curl/7.29.0,host=localhost:7080,accept=*/*,][parameters=][attributes=];

因此,在这里您看到主体rhqadmin已登录并获得了剩余用户分配的角色,该角色与web.xml中的security-constraint元素匹配。

进一步查看

我已经将以上内容作为环聊直播进行了介绍 。 不幸的是,当我在解释时打字时,G +会不时使我静音。

视频播放完后,我还有其他问题,最终让我重新思考启动阶段,以防用户安装了启用了LDAP的RHQ先前版本。 在这种情况下,安装程序仍将安装初始的仅基于DB的RHQUserSecurityDomain,然后在启动bean中检查a)系统设置中是否启用了LDAP,以及b)登录模块是否实际存在。 如果a)匹配并且它们不存在,我们将安装它们。

此Bugzilla条目还包含有关整个故事的更多信息。


翻译自: https://www.javacodegeeks.com/2013/05/creating-a-delegating-login-module-for-jboss-eap-6-1.html

jboss eap 7.0

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值