- 浏览: 1193120 次
- 性别:
- 来自: 杭州
文章分类
最新评论
-
insistboy:
写的太棒了,受不了
WebLogic11g-创建域(Domain) -
goldyeah:
厉害了 困扰我大半个月的问题解决了 谢谢博主
WebLogic11g-单双向SSL配置(以Springside3为例) -
zy315351965:
404伤不起
开源流程引擎Snaker -
nannan408:
双向的时候谷歌提示“不接受您的登录证书,或者您可能没有提供登录 ...
WebLogic11g-单双向SSL配置(以Springside3为例) -
一颗赛艇:
不成功啊。启动有问题 <Security> < ...
WebLogic11g-单双向SSL配置(以Springside3为例)
LogoutFilter过滤器对应的类路径为
org.springframework.security.web.authentication.logout.LogoutFilter
通过这个类的源码可以看出,这个类有两个构造函数
这两个构造函数的参数,是从哪里传递的呢?没错,就是之前解析http标签通过创建LogoutFilter过滤器的bean定义时通过构造参数注入进来的。下面的部分源码为LogoutFilter的bean定义
此时应该能知道,在LogoutFilter的bean实例化时,两个类变量logoutSuccessUrl、List<LogoutHandler> handlers已经通过构造函数注入到LogoutFilter的实例中来了。
接下来,继续看doFilter部分的源码
这时,可能会产生疑问。上一个过滤器SecurityContextPersistenceFilter不是只产生了一个空的SecurityContext么?就是一个没有认证信息的SecurityContext实例
这个返回的不是null么?产生这个疑问,肯定是被SecurityContextPersistenceFilter过滤器分析时误导的。实际上,每个过滤器只处理自己负责的事情,LogoutFilter只负责拦截j_spring_security_logout这个url(如果没有配置logout的url),其他的url全部跳过。其实退出功能肯定是登录到应用之后才会使用到的,登录对应的Filter肯定会把认证信息添加到SecurityContext中去的,后面再分析。
继续看LogoutHandler是如何处理退出任务的
这里的handler至少有一个SecurityContextLogoutHandler,
如果有remember me服务,就还有一个Handler。remember me的handler有两种,
如果配置了持久化信息,如(token-repository-ref、data-source-ref属性)这种的handler为:org.springframework.security.web.authentication.rememberme.PersistentTokenBasedRememberMeServices
如果没有配置,那么handler就是:org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices
先来看SecurityContextLogoutHandler
再来看remember me的handler
1.配置了持久化属性时的handler:PersistentTokenBasedRememberMeServices
2.未配置持久化属性的handler:TokenBasedRememberMeServices
这个handler没有覆盖父类的logout方法,所以直接调用父类的logout方法,仅仅清除cookie
退出成功后执行onLogoutSuccess操作,完成redirect
这个语句是直接redirect到logout标签中的logout-success-url属性定义的url
至此,整个logoutFilter任务已经完成了,总结一下,主要任务为
1.从SecurityContext中获取Authentication,然后调用每个handler处理logout
2.退出成功后跳转到指定的url
org.springframework.security.web.authentication.logout.LogoutFilter
通过这个类的源码可以看出,这个类有两个构造函数
public LogoutFilter(LogoutSuccessHandler logoutSuccessHandler, LogoutHandler... handlers) { Assert.notEmpty(handlers, "LogoutHandlers are required"); this.handlers = Arrays.asList(handlers); Assert.notNull(logoutSuccessHandler, "logoutSuccessHandler cannot be null"); this.logoutSuccessHandler = logoutSuccessHandler; } public LogoutFilter(String logoutSuccessUrl, LogoutHandler... handlers) { Assert.notEmpty(handlers, "LogoutHandlers are required"); this.handlers = Arrays.asList(handlers); Assert.isTrue(!StringUtils.hasLength(logoutSuccessUrl) || UrlUtils.isValidRedirectUrl(logoutSuccessUrl), logoutSuccessUrl + " isn't a valid redirect URL"); SimpleUrlLogoutSuccessHandler urlLogoutSuccessHandler = new SimpleUrlLogoutSuccessHandler(); if (StringUtils.hasText(logoutSuccessUrl)) { urlLogoutSuccessHandler.setDefaultTargetUrl(logoutSuccessUrl); } logoutSuccessHandler = urlLogoutSuccessHandler; }
这两个构造函数的参数,是从哪里传递的呢?没错,就是之前解析http标签通过创建LogoutFilter过滤器的bean定义时通过构造参数注入进来的。下面的部分源码为LogoutFilter的bean定义
public BeanDefinition parse(Element element, ParserContext pc) { String logoutUrl = null; String successHandlerRef = null; String logoutSuccessUrl = null; String invalidateSession = null; BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(LogoutFilter.class); if (element != null) { //分别解析logout标签的属性 Object source = pc.extractSource(element); builder.getRawBeanDefinition().setSource(source); logoutUrl = element.getAttribute(ATT_LOGOUT_URL); successHandlerRef = element.getAttribute(ATT_LOGOUT_HANDLER); WebConfigUtils.validateHttpRedirect(logoutUrl, pc, source); logoutSuccessUrl = element.getAttribute(ATT_LOGOUT_SUCCESS_URL); WebConfigUtils.validateHttpRedirect(logoutSuccessUrl, pc, source); invalidateSession = element.getAttribute(ATT_INVALIDATE_SESSION); } if (!StringUtils.hasText(logoutUrl)) { logoutUrl = DEF_LOGOUT_URL; } //向LogoutFilter中注入属性值filterProcessesUrl builder.addPropertyValue("filterProcessesUrl", logoutUrl); if (StringUtils.hasText(successHandlerRef)) { if (StringUtils.hasText(logoutSuccessUrl)) { pc.getReaderContext().error("Use " + ATT_LOGOUT_URL + " or " + ATT_LOGOUT_HANDLER + ", but not both", pc.extractSource(element)); } //如果successHandlerRef不为空,就通过构造函数注入到LogoutFilter中 builder.addConstructorArgReference(successHandlerRef); } else { // Use the logout URL if no handler set if (!StringUtils.hasText(logoutSuccessUrl)) { //如果logout-success-url没有定义,则采用默认的/ logoutSuccessUrl = DEF_LOGOUT_SUCCESS_URL; } //通过构造函数注入logoutSuccessUrl值 builder.addConstructorArgValue(logoutSuccessUrl); } if (!StringUtils.hasText(invalidateSession)) { invalidateSession = DEF_INVALIDATE_SESSION; } //默认Logout的Handler是SecurityContextLogoutHandler ManagedList handlers = new ManagedList(); SecurityContextLogoutHandler sclh = new SecurityContextLogoutHandler(); if ("true".equals(invalidateSession)) { sclh.setInvalidateHttpSession(true); } else { sclh.setInvalidateHttpSession(false); } handlers.add(sclh); //如果有remember me服务,需要添加remember的handler if (rememberMeServices != null) { handlers.add(new RuntimeBeanReference(rememberMeServices)); } //继续将handlers通过构造参数注入到LogoutFilter的bean中 builder.addConstructorArgValue(handlers); return builder.getBeanDefinition(); }
此时应该能知道,在LogoutFilter的bean实例化时,两个类变量logoutSuccessUrl、List<LogoutHandler> handlers已经通过构造函数注入到LogoutFilter的实例中来了。
接下来,继续看doFilter部分的源码
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) res; //判断是否需要退出,主要通过请求的url是否是filterProcessesUrl值来识别 if (requiresLogout(request, response)) { //通过SecurityContext实例获取认证信息 Authentication auth = SecurityContextHolder.getContext().getAuthentication(); if (logger.isDebugEnabled()) { logger.debug("Logging out user '" + auth + "' and transferring to logout destination"); } //循环LogoutHandler处理退出任务 for (LogoutHandler handler : handlers) { handler.logout(request, response, auth); } //退出成功后,进行redirect操作 logoutSuccessHandler.onLogoutSuccess(request, response, auth); return; } chain.doFilter(request, response); }
这时,可能会产生疑问。上一个过滤器SecurityContextPersistenceFilter不是只产生了一个空的SecurityContext么?就是一个没有认证信息的SecurityContext实例
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
这个返回的不是null么?产生这个疑问,肯定是被SecurityContextPersistenceFilter过滤器分析时误导的。实际上,每个过滤器只处理自己负责的事情,LogoutFilter只负责拦截j_spring_security_logout这个url(如果没有配置logout的url),其他的url全部跳过。其实退出功能肯定是登录到应用之后才会使用到的,登录对应的Filter肯定会把认证信息添加到SecurityContext中去的,后面再分析。
继续看LogoutHandler是如何处理退出任务的
for (LogoutHandler handler : handlers) { handler.logout(request, response, auth); }
这里的handler至少有一个SecurityContextLogoutHandler,
如果有remember me服务,就还有一个Handler。remember me的handler有两种,
如果配置了持久化信息,如(token-repository-ref、data-source-ref属性)这种的handler为:org.springframework.security.web.authentication.rememberme.PersistentTokenBasedRememberMeServices
如果没有配置,那么handler就是:org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices
先来看SecurityContextLogoutHandler
//完成两个任务1.让session失效;2.清除SecurityContext实例 public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) { Assert.notNull(request, "HttpServletRequest required"); if (invalidateHttpSession) { HttpSession session = request.getSession(false); if (session != null) { session.invalidate(); } } SecurityContextHolder.clearContext(); }
再来看remember me的handler
1.配置了持久化属性时的handler:PersistentTokenBasedRememberMeServices
//也完成两个任务1.清除cookie;2.从持久化中清除remember me数据 public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) { super.logout(request, response, authentication); if (authentication != null) { //如果定义了token-repository-ref属性,则通过依赖的持久化bean清除 //如果定义了data-source-ref属性,直接通过 //JdbcTokenRepositoryImpl清除数据,也就是执行delete操作 tokenRepository.removeUserTokens(authentication.getName()); } }
2.未配置持久化属性的handler:TokenBasedRememberMeServices
这个handler没有覆盖父类的logout方法,所以直接调用父类的logout方法,仅仅清除cookie
退出成功后执行onLogoutSuccess操作,完成redirect
logoutSuccessHandler.onLogoutSuccess(request, response, auth);
这个语句是直接redirect到logout标签中的logout-success-url属性定义的url
至此,整个logoutFilter任务已经完成了,总结一下,主要任务为
1.从SecurityContext中获取Authentication,然后调用每个handler处理logout
2.退出成功后跳转到指定的url
发表评论
-
Spring Security3源码分析-电子书下载
2012-07-30 14:34 8540提供电子书下载链接。 -
Spring Security3源码分析-CAS支持
2012-05-13 21:03 25769Spring Security3对CAS的支持主要在这个spr ... -
Spring Security3源码分析-SSL支持
2012-05-10 12:48 11068Sping Security3对于SSL的支持仅仅表现在对需要 ... -
Spring Security3源码分析-认证授权分析
2012-05-09 21:59 6359前面分析了FilterChainProxy执行过程,也对常用的 ... -
Spring Security3源码分析-Filter链排序分析
2012-05-09 14:39 15294通过前面Spring Security提供的各种Filter的 ... -
Spring Security3源码分析-RequestCacheAwareFilter分析
2012-05-09 12:55 4873RequestCacheAwareFilter过滤器对应的类路 ... -
Spring Security3源码分析-ExceptionTranslationFilter分析
2012-05-09 10:03 7798ExceptionTranslationFilter过滤器对应 ... -
Spring Security3源码分析-SessionManagementFilter分析-下
2012-05-08 21:03 6334很多spring security3资料在 ... -
Spring Security3源码分析-SessionManagementFilter分析-上
2012-05-08 17:26 10916SessionManagementFilter过滤 ... -
Spring Security3源码分析-AnonymousAuthenticationFilter分析
2012-05-08 10:32 5191AnonymousAuthenticationFilter ... -
Spring Security3源码分析-BasicAuthenticationFilter分析
2012-05-08 09:24 9598BasicAuthenticationFilter过滤器对应的 ... -
Spring Security3源码分析-FilterSecurityInterceptor分析
2012-05-07 17:31 15280FilterSecurityInterceptor过滤器对应的 ... -
Spring Security3源码分析-SecurityContextHolderAwareRequestFilter分析
2012-05-07 10:34 6816SecurityContextHolderAwareReque ... -
Spring Security3源码分析-RememberMeAuthenticationFilter分析
2012-05-06 22:33 5941RememberMeAuthenticationFilter过 ... -
Spring Security3源码分析-UsernamePasswordAuthenticationFilter分析
2012-05-06 11:54 24854UsernamePasswordAuthenticationF ... -
Spring Security3源码分析-SecurityContextPersistenceFilter分析
2012-05-06 08:22 8720通过观察Filter的名字,就能大概猜出来这个过滤器的作用,是 ... -
Spring Security3源码分析-FilterChainProxy执行过程分析
2012-05-06 07:48 4239通过FilterChainProxy的初始化、自定义标签的分析 ... -
Spring Security3源码分析-authentication-manager标签解析
2012-05-05 16:13 21675讲解完http标签的解析过程,authentication-m ... -
Spring Security3源码分析-http标签解析
2012-05-05 15:29 8429在FilterChainProxy初始化的 ... -
Spring Security3源码分析-FilterChainProxy初始化
2012-05-04 16:57 20047很久没有更新博客了,最近对Spring Security做了比 ...
相关推荐
class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor"> <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"> ...
这是在原来的基础上添加了logoutFilter的应用,并且有相应的博客讲解。这是一个具体的可以跑的通的demo,博客对应的地址如下:http://blog.csdn.net/yuebinghaoyuan/article/details/20690789
acegi security实践教程—简单定制logoutFilter 这个demo是在原来的基础上,定制自己的logoutFilter,具体详细的博客地址介绍如下: http://blog.csdn.net/yuebinghaoyuan/article/details/21075929
<bean id="logout" class="org.apache.shiro.web.filter.authc.LogoutFilter"> ${cas.logout.url}"/> </bean> <!-- CAS认证过滤器 --> <bean id="casFilter" class="org.apache.shiro.cas.CasFilter">...
3 = {CsrfFilter @ 7758} 4 = {LogoutFilter @ 7757} 5 = {UsernamePasswordAuthenticationFilter @ 7755} 6 = {RequestCacheAwareFilter @ 9937} 7 = {SecurityContextHolderAwareRequestFilter @ 9938} 8 = {...
不用我们去实现退出,只要去访问一个退出的url(该 url是可以不存在),由LogoutFilter拦截住,清除session。 数据回显 授权过滤器使用 XML配置方式 1.在配置文件上配置配置filter规则。/items...