Spring security 为什么Spring Security会将匿名用户重定向到expiredsessionurl
我真的很想了解SpringSecurity是如何工作的,但我现在有点不知所措。下面是一个简单的场景:Spring security 为什么Spring Security会将匿名用户重定向到expiredsessionurl,spring-security,Spring Security,我真的很想了解SpringSecurity是如何工作的,但我现在有点不知所措。下面是一个简单的场景: 用户访问网站主页但不登录 SecurityContextPersistenceFilter记录没有可用的SecurityContext,并将创建一个新的SecurityContext AnonymousAuthenticationFilter使用匿名令牌填充SecurityContextHolder 创建ID为C2A35ED5A41E29865FF53162B0024D52的会话 用户让页面处于
SecurityContextPersistenceFilter
记录没有可用的SecurityContext,并将创建一个新的SecurityContextAnonymousAuthenticationFilter
使用匿名令牌填充SecurityContextHolderSecurityContextPersistenceFilter
再次记录没有可用的SecurityContext,并将创建一个新的SecurityContextAnonymousAuthenticationFilter
再次使用匿名令牌填充SecurityContextHolderSessionManagementFilter
请求会话ID C2A35ED5A41E29865FF53162B0024D52的日志无效SessionManagementFilter
记录它正在启动新会话并重定向到/invalidsession.authorizeRequests().antMatchers(“/”、“/home”、“/about”).permitAll()。
我打开了无效会话选项来处理经过身份验证的用户:.sessionManagement().invalidSessionUrl(“/errors/invalidSession”)
。如果我注释掉该选项,那么上面描述的所有内容都完全相同,除了步骤#10-SessionManagementFilter
发现请求的会话ID无效(#9),但不会启动新会话并执行重定向(#10)
为什么??如何保持无效会话选项,但正确处理匿名用户,即不重定向?或者这是不可能的,我必须单独处理经过身份验证的用户?如果有人能帮助我了解这里发生的事情并为我指明解决问题的方向,我将非常感激。如果需要查看我的完整http配置,请告诉我
编辑
我对匿名和注册(认证)用户进行了一系列测试。如果启用了.sessionManagement().invalidSessionUrl(“/errors/invalidSession”)
,则这两种类型的用户最终都将到达错误页面。未选中Memberme的已验证用户与其他用户相同。如果选中了RememberMe,则RememberMe超时后将显示错误页面
如果禁用无效会话选项,则没有用户会获得错误页面(这是有意义的)。这两种类型的用户都可以随意浏览公共页面,经过身份验证的用户将在会话或Memberme过期后被要求登录
如果您感兴趣,这里涉及的代码位于SessionManagementFilter
if (invalidSessionStrategy != null) {
invalidSessionStrategy
.onInvalidSessionDetected(request, response);
return;
}
如果启用了.sessionManagement().invalidSessionUrl
,则调用默认方法SimpleDirectInvalidSessionStrategy
,该方法执行以下代码:
if (createNewSession) {
request.getSession();
}
redirectStrategy.sendRedirect(request, response, destinationUrl);
可以通过setCreateNewSession(布尔createNewSession)
设置createNewSession
布尔值,其描述如下:
确定是否应在重定向之前创建新会话(以避免在重定向请求中发送相同会话ID时可能出现的循环问题)。或者,确保配置的URL不会通过会话管理筛选器
因此,在我看来,
.sessionManagement().invalidSessionUrl
最适合所有页面都经过身份验证的站点。我正在查看的选项是放置在SessionManagementFilter
之前的自定义筛选器,它检查页面访问并根据需要打开/关闭“createNewSession”,或者关闭无效会话选项并在其他地方处理已验证页面(?)。在这个问题中,我还偶然发现了
,我将进一步探讨这个问题。由于对Spring Security如此陌生,我对正确处理这种情况的最佳实践没有很好的认识。任何帮助都将不胜感激。好的,所以我花了过去几周的时间在Spring Security上四处寻找,试图了解这一切是如何结合在一起的。我还在学习,但对于这种特殊情况,我发现有两种方法是有效的
显而易见的一点是绕过公共页面的安全性,如下所示:
@Override
public void configure(WebSecurity web) throws Exception
{
web
.ignoring()
.antMatchers("/", "/home", "/about", "/login**", "/thankyou", "/user/signup**", "/resources/**")
;
}
@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);
}
一般来说,我对web安全性的了解还不够,不知道这是不是一种可以接受的方法,但它允许匿名用户浏览站点,而不会出现无效的会话错误
更难的解决方案(对于像我这样的Java和Spring noob)是基于以下问题:
默认的SimpleDirectInvalidSessionStrategy
类是final
,这意味着我必须创建该类的基本副本(不确定这是一个多么好的想法)。您不能使用会话属性,因为会话在到达此策略时已被销毁,所以我为名为authUser的会话cookie创建了一个helper类(如果有人想查看,我可以发布该类)。cookie是在loginsucesshandler
或RememberMeSuccessHandler
中创建或更新的,它指示用户是匿名的还是经过身份验证的:
authCookie.setCookie(request, response, "anonymousUser");
or
authCookie.setCookie(request, response, authentication.getName());
我目前使用的实际登录仅用于测试目的——它最终将只是某种简单的是/否指示符<代码>CustomLogoutSuccessHandler将其重置为匿名用户
无效的会话方法如下所示:
@Override
public void configure(WebSecurity web) throws Exception
{
web
.ignoring()
.antMatchers("/", "/home", "/about", "/login**", "/thankyou", "/user/signup**", "/resources/**")
;
}
@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
类包括以下内容:
@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;
}
}
到目前为止,我的测试对于匿名用户和经过身份验证的用户都是成功的,但是这种方法还没有经过生产测试。我没有收到任何这样或那样的评论,所以我将接受这个答案。