- 浏览: 1201040 次
- 性别:
- 来自: 杭州
文章分类
最新评论
-
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 8615提供电子书下载链接。 -
Spring Security3源码分析-CAS支持
2012-05-13 21:03 25854Spring Security3对CAS的支持主要在这个spr ... -
Spring Security3源码分析-SSL支持
2012-05-10 12:48 11156Sping Security3对于SSL的支持仅仅表现在对需要 ... -
Spring Security3源码分析-认证授权分析
2012-05-09 21:59 6469前面分析了FilterChainProxy执行过程,也对常用的 ... -
Spring Security3源码分析-Filter链排序分析
2012-05-09 14:39 15440通过前面Spring Security提供的各种Filter的 ... -
Spring Security3源码分析-RequestCacheAwareFilter分析
2012-05-09 12:55 5014RequestCacheAwareFilter过滤器对应的类路 ... -
Spring Security3源码分析-ExceptionTranslationFilter分析
2012-05-09 10:03 7924ExceptionTranslationFilter过滤器对应 ... -
Spring Security3源码分析-SessionManagementFilter分析-下
2012-05-08 21:03 6420很多spring security3资料在 ... -
Spring Security3源码分析-SessionManagementFilter分析-上
2012-05-08 17:26 11009SessionManagementFilter过滤 ... -
Spring Security3源码分析-AnonymousAuthenticationFilter分析
2012-05-08 10:32 5292AnonymousAuthenticationFilter ... -
Spring Security3源码分析-BasicAuthenticationFilter分析
2012-05-08 09:24 9693BasicAuthenticationFilter过滤器对应的 ... -
Spring Security3源码分析-FilterSecurityInterceptor分析
2012-05-07 17:31 15384FilterSecurityInterceptor过滤器对应的 ... -
Spring Security3源码分析-SecurityContextHolderAwareRequestFilter分析
2012-05-07 10:34 6889SecurityContextHolderAwareReque ... -
Spring Security3源码分析-RememberMeAuthenticationFilter分析
2012-05-06 22:33 6020RememberMeAuthenticationFilter过 ... -
Spring Security3源码分析-UsernamePasswordAuthenticationFilter分析
2012-05-06 11:54 24940UsernamePasswordAuthenticationF ... -
Spring Security3源码分析-SecurityContextPersistenceFilter分析
2012-05-06 08:22 8845通过观察Filter的名字,就能大概猜出来这个过滤器的作用,是 ... -
Spring Security3源码分析-FilterChainProxy执行过程分析
2012-05-06 07:48 4312通过FilterChainProxy的初始化、自定义标签的分析 ... -
Spring Security3源码分析-authentication-manager标签解析
2012-05-05 16:13 21768讲解完http标签的解析过程,authentication-m ... -
Spring Security3源码分析-http标签解析
2012-05-05 15:29 8591在FilterChainProxy初始化的 ... -
Spring Security3源码分析-FilterChainProxy初始化
2012-05-04 16:57 20139很久没有更新博客了,最近对Spring Security做了比 ...
相关推荐
综上,Spring Security 3.1.3源码的分析和学习,可以帮助开发者深入理解Web安全原理,掌握如何利用这个强大的框架来保护应用程序免受攻击。通过对源码的研究,可以更清晰地了解其内部工作方式,从而更好地进行定制化...
### Spring Security 源码分析知识...以上内容涵盖了 Spring Security 3 的源码分析中几个关键点的具体内容。通过对这些内容的深入学习和理解,可以更好地掌握 Spring Security 的工作原理及其在实际项目中的应用技巧。
通过这些源码分析,我们可以了解到Spring Security是如何在背后工作,保护应用程序免受未经授权的访问。理解这些组件的工作原理对于定制和优化安全配置至关重要,同时也有助于开发者解决潜在的安全问题。
**源码分析** 深入理解Spring Security的源码有助于定制和优化你的安全解决方案。你可以从以下几个方面入手: - 认证流程:研究`AuthenticationProvider`和`UserDetailsService`的实现。 - 权限控制:查看`...
6. **源码分析**: Spring Security的源码是开源的,你可以深入研究其内部工作原理,了解每个组件是如何协同工作的。这将帮助你更好地理解和定制这个框架。 7. **工具**: - Spring Security的官方文档和教程是...
《深入剖析Spring Security源码与Spring Boot集成》 在当今的Web开发中,安全问题始终是不可忽视的重要环节。Spring Security作为Spring生态系统中的一个强大安全框架,为开发者提供了丰富的功能来保护应用程序。...
这篇博文的作者通过实际操作分享了他在使用SpringSecurity时的经验,虽然描述中并未给出具体细节,但我们可以从标题和标签中推测,本文可能涉及了SpringSecurity的源码分析和工具的使用。 SpringSecurity的核心概念...
### SpringSecurity企业级认证全套开发资源解析 #### 一、Spring Security概述与核心特性 Spring Security 是一个功能强大且高度可定制的身份验证和安全(ACL)框架。它为基于Spring的应用程序提供了声明式方法的...
通过学习和分析这些源代码,你可以深入了解Spring Security的工作原理,以及如何将其集成到你的应用程序中以实现安全控制。对于开发人员来说,理解这些核心概念和组件非常重要,因为它们构成了Spring Security强大...
而acegi,作为Spring Security早期的名字,其源码分析对于理解Spring Security的工作原理具有不可替代的价值。本文将深入解析acegi(即Spring Security)的核心组件及其实现机制。 #### acegi核心组件与工作流程 #...