首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >为什么匿名用户被Spring安全性重定向到expiredsessionurl

为什么匿名用户被Spring安全性重定向到expiredsessionurl
EN

Stack Overflow用户
提问于 2015-09-24 16:35:27
回答 1查看 3.1K关注 0票数 7

我真的想了解Security是如何工作的,但我现在有点迷失了。下面是一个简单的场景:

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

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

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

编辑

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

如果我禁用无效的会话选项,就不会有用户获得错误页面(这是有意义的)。这两种类型的用户只要愿意就可以浏览公共页面,并且经过身份验证的用户将在会话或RememberMe过期后被要求登录。

如果您感兴趣,这里涉及的代码在SessionManagementFilter

代码语言:javascript
运行
复制
if (invalidSessionStrategy != null) {
    invalidSessionStrategy
        .onInvalidSessionDetected(request, response);
    return;
}

如果启用了.sessionManagement().invalidSessionUrl,则调用默认方法SimpleRedirectInvalidSessionStrategy,该方法执行以下代码:

代码语言:javascript
运行
复制
if (createNewSession) {
    request.getSession();
}
redirectStrategy.sendRedirect(request, response, destinationUrl);

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

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

因此,在我看来,.sessionManagement().invalidSessionUrl对所有页面都经过身份验证的站点最有效。我正在查看的选项是放置在SessionManagementFilter之前的自定义筛选器,它检查页面访问并根据需要打开/关闭“createNewSession”,或者关闭无效的会话选项,并在其他地方处理通过身份验证的页面(?)。在这个问题中,我还偶然发现了<%@ page session=“false” %> -- Why set a JSP page session = “false” directive? --我将进一步研究这个问题。作为Security的新手,我对正确处理这种情况的最佳实践没有很好的了解。任何帮助都将不胜感激。

EN

Stack Overflow用户

回答已采纳

发布于 2015-10-01 22:09:34

好的,我花了几周时间在Security中进行研究,试图了解它们是如何结合在一起的。我还在学习,但在这种特殊情况下,我发现了两种可行的方法。

最明显的一点是绕过这样的公共页面的安全性:

代码语言:javascript
运行
复制
@Override
public void configure(WebSecurity web) throws Exception
{
    web
    .ignoring()
        .antMatchers("/", "/home", "/about", "/login**", "/thankyou", "/user/signup**", "/resources/**")
    ;
}

对于web安全性,我仍然不太了解,不知道这是否是一种可接受的方法,但它允许匿名用户浏览站点w/o,从而获得无效的会话错误。

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

Spring security invalid session redirect

How to set a custom invalid session strategy in Spring Security

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

代码语言:javascript
运行
复制
authCookie.setCookie(request, response, "anonymousUser");
or
authCookie.setCookie(request, response, authentication.getName());

我目前使用的实际登录仅为测试目的-它最终将只是一个简单的是/否的指示某种类型。CustomLogoutSuccessHandler将其重置为anonymousUser

无效的session方法如下所示:

代码语言:javascript
运行
复制
@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);
}

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

SecurityConfig类包括以下内容:

代码语言:javascript
运行
复制
@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;
    }
}

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

票数 2
EN
查看全部 1 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/32766594

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档