如何在 Wildfly 10/JB EAP 7 中动态修改经过身份验证的用户的安全角色 post 身份验证?

How to dynamically modify an authenticated user's security roles post authentication in 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() 方法 returns 计算它。

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

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

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

如何为已经通过身份验证的用户 modify/add 角色?

在深入研究之后,我想出了一个可行的解决方案,但我不太确定它是否干净。 None 如果以后有其他人需要灵感,我就不在这里发了。

令我不安的是没有更简洁的机制来执行此操作。此外,我不确定在并行发出多个 threads/EJB 请求时这是否会导致并发问题。此外,我没有针对集群部署进行测试或验证,以确保所有不同节点之间的安全性 roles/context 正确 propagated/updated。

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