文档章节

Spring源码解析之:Spring Security启动细节和工作模式

猪刚烈
 猪刚烈
发布于 2014/10/12 11:40
字数 1193
阅读 64
收藏 3

本文基于spring-security 3.1.1的源码进行分析。本文原文连接: 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应用的配置方式:

<filter>
        <filter-name>springSecurityFilter</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
        <init-param>
            <param-name>targetBeanName</param-name>
            <param-value>springSecurityFilterChain</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>springSecurityFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </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是需要拦截每次请求的。


本文转载自:http://blog.csdn.net/bluishglc/article/details/12709557

共有 人打赏支持
猪刚烈
粉丝 22
博文 708
码字总数 110
作品 1
海淀
程序员
私信 提问
Spring Security3源码分析-FilterChainProxy初始化

很久没有更新博客了,最近对Spring Security做了比较深入的研究。 spring security的教程网上很多: http://lengyun3566.iteye.com/category/153689 http://wenku.baidu.com/view/b0c0dc0b7...

Dead_knight
2014/01/20
0
2
Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密...

小致dad
08/03
0
0
spring-security详解

spring-security详解 引入依赖 1⃣️authorizeRequests()配置路径拦截,表明路径访问所对应的权限,角色,认证信息。 2⃣️formLogin()对应表单认证相关的配置 3⃣️httpBasic()可以配置bas...

三根头发
10/15
0
0
SpringCloud2.0入门4-springboot-admin监控

前言 上一节为springboot项目添加springboot-admin监控 学习了基于springboot1.5自己注册到admin的方法。接下来学习结合Eureka使用以及2.0的改变。 1.5spring-boot-admin集成eureka 我们继续...

ryan-miao
06/29
0
0
Spring Security总结

简介 Spring Security是一个强大的和高度可定制的身份验证和访问控制框架,它的前身是 Acegi Security。Spring Security着重于为Java应用程序提供身份验证和授权。提供了一组可以在Spring应用...

asdf08442a
09/28
0
0

没有更多内容

加载失败,请刷新页面

加载更多

node.js学习笔记之koa框架和简单爬虫练习

Koa -- 基于 Node.js 平台的下一代 web 开发框架 koa是由 Express 原班人马打造的,致力于成为一个更小、更富有表现力、更健壮的 Web 框架。 使用 koa 编写 web 应用,可以免除重复繁琐的回调...

前端小攻略
29分钟前
3
0
JavaScript中的继承及实现代码

JS虽然不像是JAVA那种强类型的语言,但也有着与JAVA类型的继承属性,那么JS中的继承是如何实现的呢? 一、构造函数继承 在构造函数中,同样属于两个新创建的函数,也是不相等的 function Fn...

peakedness丶
51分钟前
3
0
记一次面试最常见的10个Redis"刁难"问题

导读:在程序员面试过程中Redis相关的知识是常被问到的话题。作为一名在互联网技术行业打击过成百上千名的资深技术面试官,本文作者总结了面试过程中经常问到的问题。十分值得一读。 Redis在...

小刀爱编程
今天
18
0
TiDB Lab 诞生记 | TiDB Hackathon 优秀项目分享

本文由红凤凰粉凤凰粉红凤凰队的成员主笔,他们的项目 TiDB Lab 在本届 TiDB Hackathon 2018 中获得了二等奖。TiDB Lab 为 TiDB 培训体系增加了一个可以动态观测 TiDB / TiKV / PD 细节的动画...

TiDB
今天
5
0
当区块链遇到零知识证明

本文由云+社区发表 当区块链遇到零知识证明 什么是零知识证明 零知识证明的官方定义是能够在不向验证者任何有用的信息的情况下,使验证者相信某个论断是正确的。这个定义有点抽象,下面笔者举...

腾讯云加社区
今天
7
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部