文档章节

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

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

本文基于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是需要拦截每次请求的。


© 著作权归作者所有

共有 人打赏支持
猪刚烈
粉丝 22
博文 708
码字总数 110
作品 1
海淀
程序员
让Spring Security 来保护你的Spring Boot项目吧

参考资料: 书籍:Spring实战(第4版) 第9章和第14章 Spring Security 参考手册 初识 Spring Security 程序猿DD的Spring Security学习笔记 Spring Security 简介 Spring Security是一个能够为...

潇潇漓燃 ⋅ 05/19 ⋅ 0

Dubbo源码-Dubbo是如何随心所欲自定义XML标签的

叨叨 今天考虑了很久要不要写这篇文章。 距离《Dubbo源码》系列的开篇到现在已经快两个月时间了。当时是想着工作上的RPC框架使用存在一些让人头疼的问题,就来看看Dubbo给出了一套什么样的解...

Jackie_Zheng ⋅ 05/20 ⋅ 0

【spring boot 系列】spring security 实践 + 源码分析

前言 本文将从示例、原理、应用3个方面介绍 spring data jpa。 以下分析基于spring boot 2.0 + spring 5.0.4版本源码 概述 Spring Security 是一个能够为基于 Spring 的企业应用系统提供声明...

java高级架构牛人 ⋅ 06/06 ⋅ 0

深入理解Spring源码(一)-IOC容器的定位,载入,注册

前言:Spring源码继承,嵌套层次非常多,读起来非常容易晕,小伙伴们在看文章的时候一定要跟着文章的思路自己去源码里点一点,看一看,并且多看几次。就会越来越清晰。下面开始正题 1.Spring...

Meet相识_bfa5 ⋅ 05/01 ⋅ 0

SpringMVC源码剖析(二)- DispatcherServlet的前世今生

上一篇文章《SpringMVC源码剖析(一)- 从抽象和接口说起》中,我介绍了一次典型的SpringMVC请求处理过程中,相继粉墨登场的各种核心类和接口。我刻意忽略了源码中的处理细节,只列出最简单的...

相见欢 ⋅ 2013/01/05 ⋅ 25

spring源码解析系列之事件驱动模型@EventListener

说到前面 本次主要介绍监听器的实例化过程源码解析。 正文 我们跟踪@EventListener源码可以发现,背后的实现是这个类EventListenerMethodProcessor,spring应用上下文启动的时候会加载这个类...

天河2018 ⋅ 04/27 ⋅ 0

Spring-Security-OAuth2

OAuth 是一个开放标准,允许用户让第三方应用访问该用户在某一网站上存储的私密的资源(如照片,视频,联系人列表),而不需要将用户名和密码提供给第三方应用。OAuth允许用户提供一个令牌,...

李玉长 ⋅ 05/10 ⋅ 0

Spring-boot+Dubbo应用启停源码分析

背景介绍 Dubbo Spring Boot 工程致力于简化 Dubbo RPC 框架在Spring Boot应用场景的开发。同时也整合了 Spring Boot 特性: 自动装配 (比如: 注解驱动, 自动装配等). Production-Ready (比...

ralf0131 ⋅ 05/29 ⋅ 0

spring boot 1.5.4 入门和原理(二)

1 spring boot入门 1.1 环境准备 JDK 7及以上 eclipse开发工具 项目管理工具Maven 本文采用、RELEASE(或1.5.2.RELEASE)调试通过。 spring-boot相关项目源码, 码云地址:https://git.oschi...

wyait ⋅ 2017/09/18 ⋅ 0

Spring-data-commons(CVE-2018-1273)漏洞分析

  前言   CVE-2018-1273 是 Spring-data-commons近期爆出的一个可远程执行代码的漏洞,为了了解更多细节,本文将从漏洞的成因,漏洞的判定以及漏洞的利用三个方面来进行详细说明。   漏...

FreeBuf ⋅ 06/01 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

笔试题之Java基础部分【简】【一】

基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语法,集合的语法,io 的语法,虚拟机方面的语法,其他 1.length、length()和size() length针对...

anlve ⋅ 24分钟前 ⋅ 2

table eg

user_id user_name full_name 1 zhangsan 张三 2 lisi 李四 `` ™ [========] 2018-06-18 09:42:06 星期一½ gdsgagagagdsgasgagadsgdasgagsa...

qwfys ⋅ 48分钟前 ⋅ 0

一个有趣的Java问题

先来看看源码: public class TestDemo { public static void main(String[] args) { Integer a = 10; Integer b = 20; swap(a, b); System.out......

linxyz ⋅ 53分钟前 ⋅ 0

十五周二次课

十五周二次课 17.1mysql主从介绍 17.2准备工作 17.3配置主 17.4配置从 17.5测试主从同步 17.1mysql主从介绍 MySQL主从介绍 MySQL主从又叫做Replication、AB复制。简单讲就是A和B两台机器做主...

河图再现 ⋅ 今天 ⋅ 0

docker安装snmp rrdtool环境

以Ubuntu16:04作为基础版本 docker pull ubuntu:16.04 启动一个容器 docker run -d -i -t --name flow_mete ubuntu:16.04 bash 进入容器 docker exec -it flow_mete bash cd ~ 安装基本软件 ......

messud4312 ⋅ 今天 ⋅ 0

OSChina 周一乱弹 —— 快别开心了,你还没有女友呢。

Osc乱弹歌单(2018)请戳(这里) 【今日歌曲】 @莱布妮子 :分享吴彤的单曲《好春光》 《好春光》- 吴彤 手机党少年们想听歌,请使劲儿戳(这里) @clouddyy :小萝莉街上乱跑,误把我认错成...

小小编辑 ⋅ 今天 ⋅ 8

Java 开发者不容错过的 12 种高效工具

Java 开发者常常都会想办法如何更快地编写 Java 代码,让编程变得更加轻松。目前,市面上涌现出越来越多的高效编程工具。所以,以下总结了一系列工具列表,其中包含了大多数开发人员已经使用...

jason_kiss ⋅ 昨天 ⋅ 0

Linux下php访问远程ms sqlserver

1、安装freetds(略,安装在/opt/local/freetds 下) 2、cd /path/to/php-5.6.36/ 进入PHP源码目录 3、cd ext/mssql进入MSSQL模块源码目录 4、/opt/php/bin/phpize生成编译配置文件 5、 . ./...

wangxuwei ⋅ 昨天 ⋅ 0

如何成为技术专家

文章来源于 -- 时间的朋友 拥有良好的心态。首先要有空杯心态,用欣赏的眼光发现并学习别人的长处,包括但不限于工具的使用,工作方法,解决问题以及规划未来的能力等。向别人学习的同时要注...

长安一梦 ⋅ 昨天 ⋅ 0

Linux vmstat命令实战详解

vmstat命令是最常见的Linux/Unix监控工具,可以展现给定时间间隔的服务器的状态值,包括服务器的CPU使用率,内存使用,虚拟内存交换情况,IO读写情况。这个命令是我查看Linux/Unix最喜爱的命令...

刘祖鹏 ⋅ 昨天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部