为什么匿名用户会被Spring Security重定向到expiredsessionurl

2023-12-28

我真的很想了解 Spring Security 是如何工作的,但目前我有点迷失。这是一个简单的场景:

  1. 用户访问网站首页但未登录
  2. SecurityContextPersistenceFilter记录没有可用的 SecurityContext 并且将创建一个新的
  3. AnonymousAuthenticationFilter使用匿名令牌填充 SecurityContextHolder
  4. 创建一个会话,ID = C2A35ED5A41E29865FF53162B0024D52
  5. 用户让页面闲置直到会话超时
  6. 用户单击“关于”页面(或再次单击主页)
  7. SecurityContextPersistenceFilter再次记录没有可用的 SecurityContext,并将创建一个新的
  8. AnonymousAuthenticationFilter再次使用匿名令牌填充 SecurityContextHolder
  9. SessionManagementFilter请求会话 ID C2A35ED5A41E29865FF53162B0024D52 的日志无效
  10. SessionManagementFilter记录它正在启动新会话并重定向到 /invalid 会话

这些页面被配置为.authorizeRequests().antMatchers("/","/home","/about").permitAll().我打开了无效会话选项来处理经过身份验证的用户:.sessionManagement().invalidSessionUrl("/errors/invalidSession")。如果我注释掉该选项,那么上面描述的所有内容都完全相同,除了步骤 #10 -SessionManagementFilter看到请求的会话 ID 无效 (#9),但不会启动新会话并执行重定向 (#10)。

为什么?我该怎么做才能保留无效的会话选项,但正确处理匿名用户,即不被重定向?或者这是不可能的,我必须单独处理经过身份验证的用户?如果有人能帮助我了解这里发生的事情并为我指明解决此问题的方向,我将非常感激。如果您需要查看我的完整 http 配置,请告诉我。

EDIT

我对匿名和注册(经过身份验证)的用户进行了一系列测试。如果.sessionManagement().invalidSessionUrl("/errors/invalidSession")启用后,两种类型的用户最终都会到达错误页面。未选中 RememberMe 的经过身份验证的用户与匿名用户相同。如果选中 RememberMe,则 RememberMe 超时后会出现错误页面。

如果我禁用无效会话选项,则任何用户都不会收到错误页面(这是有道理的)。两种类型的用户都可以随意浏览公共页面,并且在会话或 RememberMe 过期后,将要求经过身份验证的用户登录。

如果您有兴趣,这里涉及的代码位于SessionManagementFilter

if (invalidSessionStrategy != null) {
    invalidSessionStrategy
        .onInvalidSessionDetected(request, response);
    return;
}

If .sessionManagement().invalidSessionUrl已启用默认方法SimpleRedirectInvalidSessionStrategy被调用,它执行这段代码:

if (createNewSession) {
    request.getSession();
}
redirectStrategy.sendRedirect(request, response, destinationUrl);

The createNewSession布尔值可以通过设置setCreateNewSession(boolean createNewSession),描述为:

确定在重定向之前是否应创建新会话(以避免随重定向请求发送相同会话 ID 时可能出现的循环问题)。或者,确保配置的 URL 不会通过SessionManagementFilter.

所以,在我看来就像.sessionManagement().invalidSessionUrl最适合所有页面都经过身份验证的网站。我正在查看的选项是放置在SessionManagementFilter检查页面访问并根据需要打开/关闭“createNewSession”,或者关闭无效会话选项并在其他地方处理经过身份验证的页面(?)。我也偶然发现<%@ page session=“false” %>在这个问题中 -为什么要设置 JSP 页面 session = “false” 指令? https://stackoverflow.com/questions/5515729/why-set-a-jsp-page-session-false-directive- 我将进一步研究。作为 Spring Security 的新手,我对正确处理这种情况的最佳实践没有很好的认识。任何帮助,将不胜感激。


好的,过去几周我一直在研究 Spring Security,试图了解它们是如何组合在一起的。我仍在学习,但对于这种特殊情况,我发现了两种有效的方法。

最明显的就是绕过公共页面的安全性,如下所示:

@Override
public void configure(WebSecurity web) throws Exception
{
    web
    .ignoring()
        .antMatchers("/", "/home", "/about", "/login**", "/thankyou", "/user/signup**", "/resources/**")
    ;
}

我对网络安全总体了解还不够,不知道这是否是可接受的方法,但它允许匿名用户浏览网站而不会出现无效会话错误。

更难的解决方案(对于像我这样的 Java 和 Spring 菜鸟来说)是基于这些 SO 问题:

Spring Security 无效会话重定向 https://stackoverflow.com/questions/30465618/spring-security-invalid-session-redirect

如何在 Spring Security 中设置自定义无效会话策略 https://stackoverflow.com/questions/25809367/how-to-set-a-custom-invalid-session-strategy-in-spring-security

默认SimpleRedirectInvalidSessionStrategy类是final这意味着我必须基本上创建该类的副本(不确定这是一个多好的想法)。您不能使用会话属性,因为会话在达到此策略时已被销毁,因此我为会话 cookie 创建了一个名为 authUser 的帮助程序类(如果有人想查看它,我可以发布该类)。 cookie 是在以下位置创建或更新的:LoginSuccessHandler or RememberMeSuccessHandler它指示用户是匿名还是经过身份验证:

authCookie.setCookie(request, response, "anonymousUser");
or
authCookie.setCookie(request, response, authentication.getName());

我目前仅将实际登录用于测试目的 - 它最终只是某种简单的是/否指示器。CustomLogoutSuccessHandler将其重置为匿名用户

无效的会话方法如下所示:

@Override
public void onInvalidSessionDetected(HttpServletRequest request, HttpServletResponse response) 
    throws IOException, ServletException {

    String url = destinationUrl;

    //reset context default value
    redirectStrategy.setContextRelative(false);

    if (authCookie.isCurrentCookieAnonymous()) {
        //pass the URL originally requested by the anonymous user
        url = request.getRequestURI();
        //the URL needs to have the context removed
        redirectStrategy.setContextRelative(true);
    }

    //always revert to anonymous user
    authCookie.setCookie(request, response, "anonymousUser");

    logger.debug("Starting new session (if required) and redirecting to '" + url + "'");

    if (createNewSession)
        request.getSession();

    redirectStrategy.sendRedirect(request, response, url);
}

同样,如果需要,我可以发布完整的课程。

The SecurityConfig类包括以下内容:

@Bean
public SessionManagementBeanPostProcessor sessionManagementBeanPostProcessor() {
    return new SessionManagementBeanPostProcessor();
}

protected static class SessionManagementBeanPostProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) {
        if (bean instanceof SessionManagementFilter) {
            SessionManagementFilter filter = (SessionManagementFilter) bean;
            filter.setInvalidSessionStrategy(new RedirectInvalidSession("/errors/invalidSession"));
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) {
        return bean;
    }
}

到目前为止,我的测试对于匿名用户和经过身份验证的用户都是成功的,但这种方法尚未经过生产测试。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么匿名用户会被Spring Security重定向到expiredsessionurl 的相关文章

随机推荐