我真的想了解Security是如何工作的,但我现在有点迷失了。下面是一个简单的场景:
SecurityContextPersistenceFilter
记录没有SecurityContext可用,并将创建一个新的AnonymousAuthenticationFilter
用匿名令牌填充SecurityContextHolderSecurityContextPersistenceFilter
再次记录没有可用的SecurityContext,并将创建一个新的AnonymousAuthenticationFilter
再次使用匿名令牌填充SecurityContextHolder。SessionManagementFilter
日志C2A35ED5A41E29865FF53162B0024D52无效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
中
if (invalidSessionStrategy != null) {
invalidSessionStrategy
.onInvalidSessionDetected(request, response);
return;
}
如果启用了.sessionManagement().invalidSessionUrl
,则调用默认方法SimpleRedirectInvalidSessionStrategy
,该方法执行以下代码:
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的新手,我对正确处理这种情况的最佳实践没有很好的了解。任何帮助都将不胜感激。
发布于 2015-10-01 22:09:34
好的,我花了几周时间在Security中进行研究,试图了解它们是如何结合在一起的。我还在学习,但在这种特殊情况下,我发现了两种可行的方法。
最明显的一点是绕过这样的公共页面的安全性:
@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是在LoginSuccessHandler
或RememberMeSuccessHandler
中创建或更新的,它指示用户是匿名的还是身份验证的:
authCookie.setCookie(request, response, "anonymousUser");
or
authCookie.setCookie(request, response, authentication.getName());
我目前使用的实际登录仅为测试目的-它最终将只是一个简单的是/否的指示某种类型。CustomLogoutSuccessHandler
将其重置为anonymousUser
无效的session方法如下所示:
@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;
}
}
到目前为止,我的测试对于匿名用户和经过身份验证的用户都是成功的,但是这种方法还没有经过生产测试。
https://stackoverflow.com/questions/32766594
复制相似问题