SecurityContextLogoutHandler即使设置为“false”,也会清除认证

4

我目前正在尝试在Spring Boot 2中使用Spring Security实现应用程序的注销机制。

我的Spring Security注销配置如下:

http
    .logout()
    .logoutRequestMatcher(new AntPathRequestMatcher("/logout.html"))
    .logoutSuccessHandler(logoutSuccessHandler)
    .addLogoutHandler(handler1)
    .addLogoutHandler(handler2)
    .clearAuthentication(false);

使用这个配置,Spring将两个处理器添加到LogoutFilter中,同时将Spring自己的SecurityContextLogoutHandler作为处理器链中的最后一个处理器。

我们面临的问题是,在我们自定义的LogoutSuccessHandler中,我需要访问安全上下文中存储的一些变量,但即使在将.clearAuthentication(boolean clearAuthentication)设置为false时,上下文也会在SecurityContextLogoutHandler中被清除。

我真正不理解的是SecurityContextLogoutHandlerlogout方法的实现方式。

public void logout(HttpServletRequest request, HttpServletResponse response,
        Authentication authentication) {
    Assert.notNull(request, "HttpServletRequest required");
    if (invalidateHttpSession) {
        HttpSession session = request.getSession(false);
        if (session != null) {
            logger.debug("Invalidating session: " + session.getId());
            session.invalidate();
        }
    }

    if (clearAuthentication) {
        SecurityContext context = SecurityContextHolder.getContext();
        context.setAuthentication(null);
    }

    SecurityContextHolder.clearContext();
}

即使我将clearAuthentication设置为false,由于该方法的最后一行SecurityContextHolder.clearContext();会清除它,因此实际上并没有任何意义。
那么clearAuthentication标志的意义是什么?如果需要保留Authentication,该如何操作?

“Authentication”被传递到“LogoutSuccessHandler”,那么为什么您需要另一种获取它的方式呢? - M. Deinum
1个回答

1
我查看了源代码和文档,这是基于Spring Security版本4.2.X的。 SecurityContextHolder.clearContext(); 不清除上下文的内容,而是将其从SecurityContextHolder的持有策略中移除。 此外,以下策略可用:
- ThreadLocal - Inheritable ThreadLocal - Global
我相信有人会指出在哪里阅读这些不同的策略,但这与本答案无关。
“clearAuthentication”标志有什么意义? JavaDocs说:“如果为true,则从SecurityContext中删除身份验证以防止并发请求问题。”
也就是说,在这种特定情况下,它与您要尝试做的事情几乎没有关系。
如何保留身份验证信息(Authentication)?
您需要实现 LogoutSuccessHandler,其中认证(Authentication)对象直接传递给onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication)方法。 您无需进行其他操作即可访问该对象。

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