首页 > 解决方案 > 如何在 Wildfly 10/JB EAP 7 中动态修改经过身份验证的用户的安全角色后身份验证?

问题描述

我在 Wildfly 10 / JBoss EAP 7.0.8 上运行 JEE 应用程序,其中用户通过 JAAS 登录模块进行身份验证。我的安全域定义如下:

           <security-domain name="webapp" cache-type="default">
                <authentication>
                    <login-module code="org.sso.keycloak.KeycloakLoginModule" flag="optional" module="deployment.ear">
                        <module-option name="keycloak-config-file" value="${keycloak.config}"/>
                    </login-module>
                    <login-module code="security.jboss.ServerLoginModule" flag="requisite" module="deployment.ear">
                        <module-option name="password-stacking" value="useFirstPass"/>
                        <module-option name="unauthenticatedIdentity" value="nobody"/>
                    </login-module>
                </authentication>
            </security-domain>

然后我的登录模块计算给定用户的角色并通过作为 LoginModule 一部分的 getRoleSets() 方法返回它。

身份验证过程正常工作,但是我现在有一个要求,一旦他们已经通过身份验证,我需要更改经过身份验证的用户的角色。

如果我尝试为已通过身份验证的用户再次调用 request.login() ,则会引发用户已登录的异常。

从请求对象中检索委托人不会让我访问他的角色或组。我也无法找到从 SecurityContext 中检索信息的方法。

如何为已通过身份验证的用户修改/添加角色?

标签: wildflyjaas

解决方案


经过一番挖掘后,我想出了一个可行的解决方案,但我不太确定它是否干净。尽管如此,如果其他人将来需要灵感,我还是把它贴在这里。

我很不安,没有更清洁的机制可以做到这一点。此外,我不确定这是否会在并行发出多个线程/EJB 请求时导致并发问题。此外,我没有针对集群部署进行测试或验证,以确保安全角色/上下文在所有不同节点之间正确传播/更新。

RedHat 反对这种做法,并且不支持 JBoss 平台。

       // get the group containing the security roles from the user's current security context
        Optional<Group> rolesGroup = SecurityContextAssociation.getSubject().getPrincipals(Group.class).stream().filter(p->"Roles".equals(p.getName())).findFirst();
        if( rolesGroup.isPresent()){
            Group roles = rolesGroup.get();
            // remove all security roles from the current security context
            Collections.list(roles.members()).stream().forEach(principal -> roles.removeMember(principal) );
            // add the user's newly calculated security roles back into the user's security context
            Arrays.stream(newRoles).forEach( roleName -> roles.addMember(new SimplePrincipal(roleName)));
        }

推荐阅读