Spring Security在Wildfly上:执行过滤器链时出现错误

197

我正在尝试将 Spring Security SAML 扩展Spring Boot 集成。

关于这个问题,我已经开发了一个完整的示例应用程序。其源代码可以在 GitHub 上获取:

通过将其作为 Spring Boot 应用程序运行(运行在内置应用服务器上),WebApp 可以正常工作。

不幸的是,同样的认证流程在 Undertow/WildFly 上根本不能工作。

根据日志,IdP 实际执行了 AuthN 流程:我的自定义 UserDetails 实现的指令被正确执行。尽管执行流程正确,但 Spring 并没有设置和持久化当前用户的权限。

@Component
public class SAMLUserDetailsServiceImpl implements SAMLUserDetailsService {

    // Logger
    private static final Logger LOG = LoggerFactory.getLogger(SAMLUserDetailsServiceImpl.class);

    @Override
    public Object loadUserBySAML(SAMLCredential credential)
            throws UsernameNotFoundException, SSOUserAccountNotExistsException {
        String userID = credential.getNameID().getValue();
        if (userID.compareTo("jdoe@samplemail.com") != 0) {     // We're simulating the data access.
            LOG.warn("SSO User Account not found into the system");
            throw new SSOUserAccountNotExistsException("SSO User Account not found into the system", userID);
        }
        LOG.info(userID + " is logged in");
        List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
        GrantedAuthority authority = new SimpleGrantedAuthority("ROLE_USER");
        authorities.add(authority);
        ExtUser userDetails = new ExtUser(userID, "password", true, true, true,
                true, authorities, "John", "Doe");
        return userDetails;
    }
}

调试过程中,我发现问题出在 FilterChainProxy 类上。运行时,ServletRequest 的属性 FILTER_APPLIEDnull,因此 Spring 清除了 SecurityContextHolder

private final static String FILTER_APPLIED = FilterChainProxy.class.getName().concat(".APPLIED");

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
        throws IOException, ServletException {
    boolean clearContext = request.getAttribute(FILTER_APPLIED) == null;
    if (clearContext) {
        try {
            request.setAttribute(FILTER_APPLIED, Boolean.TRUE);
            doFilterInternal(request, response, chain);
        } finally {
            SecurityContextHolder.clearContext();
            request.removeAttribute(FILTER_APPLIED);
        }
    } else {
        doFilterInternal(request, response, chain);
    }
}

VMware vFabric tc SeverTomcat 上,一切都运行得非常好。你有任何解决此问题的想法吗?


2
在大多数情况下,应该在请求后清除SecurityContextHolder。该代码的唯一目的是在同一请求中应用过滤器链超过一次的情况下(在这种情况下,只有原始链应该清除上下文)。因此,我认为这不是一个问题。 - Shaun the Sheep
2
顺便提一下,这种行为每次都会使登录过程失效。有没有办法修复它,例如通过正确配置我的AS软件来解决? - vdenotaris
1
不确定您所指的是什么行为,以及如何使登录失效?当线程完成处理请求时清除上下文是正常行为 - 这对于防止将线程本地数据泄漏回线程池非常重要。此时,通常应将上下文缓存在用户会话中。因此,它不应使登录失效。 - Shaun the Sheep
2
正如上文所述,在 SSO 之后,应用服务器会清除会话数据和认证数据。这只会在 Wildfly 中发生:相同的代码在 Tomcat 中可以正常工作。 - vdenotaris
11
SecurityContextHolder.clearContext()并不清除会话数据,它只是在将线程放回线程池之前清除上下文的ThreadLocal存储。我的观点是,这应该始终发生在请求结束时,所以你看到的情况是正常的,不太可能是问题的原因。 - Shaun the Sheep
显示剩余4条评论
1个回答

7

经过调查,我注意到在认证请求中存在cookie和引用者的混乱问题。

目前,只要将Web应用程序上下文更改为根上下文,WildFly身份验证就可以正常工作:

 <server name="default-server" default-host="webapp">
     <http-listener name="default" socket-binding="http"/>
     <host name="default-host" alias="localhost" default-web-module="sso.war"/>
 </server>

重启wildfly并清除cookies后,所有内容应该正常工作。

如果您熟悉WildFly和JBOSS,这是一个不错的解决方案。您可以查看以下问题:https://dev59.com/orfna4cB1Zd3GeqPw62r - ZINE Mahmoud

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接