原文地址:http://blog.csdn.net/bluishglc/article/details/12709557

Spring-Security的启动加载细节
 
Spring-Security的启动和Spring框架的启动是一致的,都是从加载并解析xml配置文件开始的,spring通过注册自己的ServletContextListener:ContextLoaderListener,来监听ServletContext,一旦ServletContext建立完成,spring就开始加载并解析配置文件,然后初始化ioc容器了,具体的方法调用为:
 
org.springframework.web.context.ContextLoaderListener#contextInitialized

->org.springframework.web.context.ContextLoader#initWebApplicationContext

    ->org.springframework.web.context.ContextLoader#configureAndRefreshWebApplicationContext
        ->org.springframework.context.support.AbstractApplicationContext#refresh
 
到了refresh方法之后,开始进行一系列实质性的动作了,本文关心的两个重要的动作见下图注释。这里有一点需要明确的是spring的bean解析和创建bean是两个独立的过程,在解析时生成的一种叫beandefinition的对象(存放于beanFactory的beanDefinitionMap里)代表一个将要创建的bean实例的诸多信息(如bean的class类名,构造参数,是singleton还是prototype等等)用于指导bean的创建。创建出来的bean实例存放于beanFactory的xxxxBeanMap、xxxxSingletonObjects等集合字段中。

每一个过程:  加载spring security的配置文件
 
通过下述方法调用加载spring security的xml配置文件

org.springframework.web.context.ContextLoaderListener#contextInitialized
->org.springframework.web.context.ContextLoader#initWebApplicationContext
    ->org.springframework.web.context.ContextLoader#configureAndRefreshWebApplicationContext
        ->org.springframework.context.support.AbstractApplicationContext#refresh
    ->org.springframework.context.support.AbstractApplicationContext#obtainFreshBeanFactory
        ->org.springframework.context.support.AbstractRefreshableApplicationContext#refreshBeanFactory
            ->org.springframework.web.context.support.XmlWebApplicationContext#loadBeanDefinitions
                ->org.springframework.beans.factory.xml.XmlBeanDefinitionReader#loadBeanDefinitions // 自此处开始读取spring的配置文件并解析之
->org.springframework.beans.factory.xml.XmlBeanDefinitionReader#doLoadBeanDefinitions

->org.springframework.beans.factory.xml.XmlBeanDefinitionReader#registerBeanDefinitions

->org.springframework.beans.factory.xml.XmlBeanDefinitionReader#createReaderContext

->org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader#doRegisterBeanDefinitions

->org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader#parseBeanDefinitions

->org.springframework.beans.factory.xml.BeanDefinitionParserDelegate#parseCustomElement

->org.springframework.security.config.SecurityNamespaceHandler#parse

在org.springframework.beans.factory.xml.BeanDefinitionParserDelegate#parseCustomElement方法中,由于namespaceUri是http://www.springframework.org/schema/security,所以使用对应的Handler:
org.springframework.security.config.SecurityNamespaceHandler来解析配置文件。我们可以从这个Handler的Parser列表中看来spring security下的所有一级元素对应的parser.

接下来,handler.parse()方法会根据当前的element,找到对应的parser进行解析。在我们的示例中,当前元素是<http/>,所以会使用org.springframework.security.config.http.HttpSecurityBeanDefinitionParser来解析<http/>元素。
 
org.springframework.security.config.http.HttpSecurityBeanDefinitionParser#parse
        ->org.springframework.security.config.http.HttpSecurityBeanDefinitionParser#createFilterChain
            ->org.springframework.security.config.http.HttpSecurityBeanDefinitionParser#createSecurityFilterChainBean
 
方法org.springframework.security.config.http.HttpSecurityBeanDefinitionParser#createFilterChain的一个重要的动作,那就是根据用户的配置信息(这些信息已经包含在了各种builder中了,也就是代码中的HttpConfigurationBuilder httpBldr,AuthenticationConfigBuilder authBldr 等)创建相关的Filter以及FilterChain(一个org.springframework.security.web.DefaultSecurityFilterChain)自身。不过这个方法创建的Filter和FilterChain都不是对应Class的真实实例,而只是一些place  holer(org.springframework.beans.factory.config.RuntimeBeanReference),到这个方法结束时它们的实例还没有初始化.
第二个过程:实例化bean
 
当所有element对应的parser都完成解析之后,就开始创建bean的实例了(包括filter这些inner bean),这个过程发生成在方法org.springframework.context.support.AbstractApplicationContext#invokeBeanFactoryPostProcessors中,至于具体的初始化过程将在专门的一篇文章里描述,本文不再深究。
 
Spring-Security的切入点
 
spring security的整个工作模式是通过Servlet中的Filter机制,创建一个由多种Filter和Interceptor组成的FilterChain来实现的,以下是标准的spring-security嵌入web应用的配置方式:
 
  1. <filter>
  2. <filter-name>springSecurityFilter</filter-name>
  3. <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
  4. <init-param>
  5. <param-name>targetBeanName</param-name>
  6. <param-value>springSecurityFilterChain</param-value>
  7. </init-param>
  8. </filter>
  9. <filter-mapping>
  10. <filter-name>springSecurityFilter</filter-name>
  11. <url-pattern>/*</url-pattern>
  12. </filter-mapping>
这里配置了一个servlet的filter,这个filter本身并不处理具体的请求,它其实是一个filter chain,它内部包含了一个由多个spring security提供的filter的list,它负责把请求委派给list中的每一个filter进行处理。
 
这个springSecurityFilterChain的类型是:DefaultSecurityFilterChain,它和它包含的大部分filter都是spring security包提供的类,如前文所述,这些filter实例都是spring的inner bean,是由spring隐式地初始化并置于容器中管理的。以下就是某种配置下spring建立起来的filter列表:

这里捡两个重要的filter说一下:
 
UsernamePasswordAuthenticationFilter:该filter用于用户初次登录时验证用户身份(authentication)。该filter只在初次认证时存在,一旦认证通过将会从 filter chain中移除。
 
FilterSecurityInterceptor:当用户登入成功之后,每次发送请求都会使用该filter检查用户是否已经通过了认证。如果通过了认证,就放行,否则转向登录页面。
 
两个filter的差别在于: 第一个负责初次登入时的用户检查,这个检查需要根据用户提供的用户名和密码去数据库核对,若存在,将相关信息封装在一个Authentication对象中。这个filter可以说是处理初次登录时的authentication工作。而第二个filter则不需要像每个filter每次都去查询数据库,它只需要从 security context中查看当前请求用户对应的Authentication 对象是否已经存在就可以了,这个filter处理的是登入成功之后的authentication工作。这个filter是需要拦截每次请求的。

Spring源码解析之:Spring Security启动细节和工作模式--转载的更多相关文章

  1. Spring源码解析系列汇总

    相信我,你会收藏这篇文章的 本篇文章是这段时间撸出来的Spring源码解析系列文章的汇总,总共包含以下专题.喜欢的同学可以收藏起来以备不时之需 SpringIOC源码解析(上) 本篇文章搭建了IOC源 ...

  2. Spring源码解析之BeanFactoryPostProcessor(三)

    在上一章中笔者介绍了refresh()的<1>处是如何获取beanFactory对象,下面我们要来学习refresh()方法的<2>处是如何调用invokeBeanFactor ...

  3. Spring源码解析 - AbstractBeanFactory 实现接口与父类分析

    我们先来看类图吧: 除了BeanFactory这一支的接口,AbstractBeanFactory主要实现了AliasRegistry和SingletonBeanRegistry接口. 这边主要提供了 ...

  4. Spring5源码解析-论Spring DispatcherServlet的生命周期

    Spring Web框架架构的主要部分是DispatcherServlet.也就是本文中重点介绍的对象. 在本文的第一部分中,我们将看到基于Spring的DispatcherServlet的主要概念: ...

  5. spring 源码解析

    1. [文件] spring源码.txt ~ 15B     下载(167) ? 1 springн┤┬вио╬Ш: 2. [文件] spring源码分析之AOP.txt ~ 15KB     下载( ...

  6. Spring源码分析专题 —— IOC容器启动过程(上篇)

    声明 1.建议先阅读<Spring源码分析专题 -- 阅读指引> 2.强烈建议阅读过程中要参照调用过程图,每篇都有其对应的调用过程图 3.写文不易,转载请标明出处 前言 关于 IOC 容器 ...

  7. Spring源码解析——循环依赖的解决方案

    一.前言 承接<Spring源码解析--创建bean>.<Spring源码解析--创建bean的实例>,我们今天接着聊聊,循环依赖的解决方案,即创建bean的ObjectFac ...

  8. Spring源码解析-ioc容器的设计

    Spring源码解析-ioc容器的设计 1 IoC容器系列的设计:BeanFactory和ApplicatioContext 在Spring容器中,主要分为两个主要的容器系列,一个是实现BeanFac ...

  9. Spring源码解析之PropertyPlaceholderHelper(占位符解析器)

    Spring源码解析之PropertyPlaceholderHelper(占位符解析器) https://blog.csdn.net/weixin_39471249/article/details/7 ...

随机推荐

  1. django 搭建自己的博客

    原文链接:http://www.errdev.com/post/4/ 每一个爱折腾的程序员都有自己的博客,好吧,虽然我不太喜欢写博客,但是这样骚包的想法却不断涌现.博客园虽好,可以没有完全的掌控感,搭 ...

  2. 20160512关于mac安装caffe的记录

    记得2015年在mac系统上安装过一次caffe,非常顺利,但是最近群里许多同学反映mac安装caffe出现了各种问题,同时我也在帮助别人安装caffe的时候也遇到了一些坑,不再像以前这么顺利了.估计 ...

  3. 转】腾讯云CentOS 6.6安装 Nginx

    原博文出自于: http://www.cnblogs.com/xdp-gacl/p/5290155.html 感谢! 一.下载Nginx 从Nginx的官网(http://nginx.org/en/d ...

  4. windows 无法启动asp.net 状态服务 错误 0x8007277a

    处理方法:如果在启动ASP.NET State Service服务时遇到问题0x8007277a即无法启动或初始化,请尝试在命令行(CMD)中输入netsh winsock  reset(有可能是wi ...

  5. 数据结构(C语言版)---第三章栈和队列 3.4.2 队列的链式表示和实现(循环队列)

    这个是循环队列的实现,至于串及数组这两章,等有空再看,下面将学习树. 源码如下: #include <stdio.h> #include <stdlib.h> #define ...

  6. 查询processlist具体信息

    SELECT * FROM information_schema.PROCESSLIST WHERE HOST LIKE '%172.16.10.22%' AND COMMAND <> ' ...

  7. 非阻塞同步机制与CAS操作

    锁的劣势 Java在JDK1.5之前都是靠synchronized关键字保证同步的,这种通过使用一致的锁定协议来协调对共享状态的访问,可以确保无论哪个线程 持有守护变量的锁,都采用独占的方式来访问这些 ...

  8. 阿里聚安全攻防挑战赛第三题Android PwnMe解题思路

    阿里聚安全攻防挑战赛第三题Android PwnMe解题思路 大家在聚安全挑战赛正式赛第三题中,遇到android app 远程控制的题目.我们今天带你一探究竟,如何攻破这道题目. 一.题目 购物应用 ...

  9. Cipher Message

    http://acm.hust.edu.cn/vjudge/contest/view.action?cid=34121#problem/C // File Name: c.cpp // Author: ...

  10. iOS开发-UIColor转UIIamge方法

    只能说太神奇了,完美应用到我的毕业设计 - (UIImage*) createImageWithColor: (UIColor*) color { CGRect rect=CGRectMake(,,s ...