You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JBoss下Java8无Spring应用:SAML认证后@RolesAllowed在EJB中失效

解决EJB @RolesAllowed与Keycloak SAML适配器兼容问题

核心原因

@Stateless EJB的安全验证依赖JBoss的JAAS上下文,而Keycloak Servlet Filter适配器默认仅填充Web层(HttpServletRequest)的角色,未将角色同步到EJB使用的JAAS Subject中;旧LDAP配置可能残留了EJB专属的安全域配置,导致EJB仍在使用旧的认证源。

具体解决步骤

  • 统一Web与EJB的安全域
    打开JBoss的standalone.xml(或domain.xml),找到<security-domains>节点,确保Keycloak配置的安全域(通常名为keycloak)被Web和EJB同时使用。修改应用的jboss-web.xml和jboss-ejb3.xml,指定<security-domain>keycloak</security-domain>,替代旧的LDAP安全域。

  • 配置Keycloak角色映射到JAAS上下文
    在应用的keycloak.json中添加角色映射规则,确保IdP返回的角色被正确注入到JAAS Subject:

    {
      "realm": "your-realm",
      "auth-server-url": "https://your-keycloak-url/auth",
      "resource": "your-client-id",
      "role-mappings": {
        "user_role": ["user_role"]
      },
      "principal-attribute": "preferred_username",
      "use-resource-role-mappings": true
    }
    

    同时在web.xml中声明安全角色,与EJB的@RolesAllowed对应:

    <security-role>
      <role-name>user_role</role-name>
    </security-role>
    
  • 验证JAAS Subject的角色
    在Servlet中添加调试代码,确认JAAS上下文是否包含目标角色:

    import org.jboss.security.SecurityContextAssociation;
    import javax.security.auth.Subject;
    import java.util.Set;
    
    // 在认证后的Servlet方法中执行
    Subject subject = SecurityContextAssociation.getSubject();
    Set<Principal> principals = subject.getPrincipals();
    principals.forEach(p -> System.out.println("Principal: " + p.getName()));
    

    如果输出中没有user_role,说明Keycloak未将角色同步到JAAS,需要检查Keycloak客户端的角色配置(确保客户端已关联该角色,且用户拥有该角色)。

  • 清理旧LDAP残留配置
    删除standalone.xml中未使用的LDAP安全域,检查应用的ejb-jar.xml或jboss-ejb3.xml,确保没有指定旧的LDAP安全域或自定义安全配置。

为什么移除@Stateless就正常?

移除@Stateless后,类变为普通POJO,不会触发JBoss的EJB容器安全校验,直接使用Web层的HttpServletRequest角色上下文,因此@RolesAllowed注解实际未被容器校验,自然不会抛出异常。

内容的提问来源于stack exchange,提问作者h.karimi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 21:10:33