springSecurty启动流程

首先EnableWebSecurity 注解导入了WebSecurityConfiguration配置类

@Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME)
@Target(value = { java.lang.annotation.ElementType.TYPE })
@Documented
@Import({ WebSecurityConfiguration.class,SpringWebMvcImportSelector.class,OAuth2ImportSelector.class })
@EnableGlobalAuthentication
@Configuration
public @interface EnableWebSecurity {}

首先看这个类org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration
代码如下

@Autowired(required = false)public void setFilterChainProxySecurityConfigurer(ObjectPostProcessor<Object> objectPostProcessor,@Value("#{@autowiredWebSecurityConfigurersIgnoreParents.getWebSecurityConfigurers()}") List<SecurityConfigurer<Filter, WebSecurity>> webSecurityConfigurers)throws Exception {//通过AutowireBeanFactoryObjectPostProcessor将WebSecurity注入到spring容器中//WebSecurity是AutowireBeanFactoryObjectPostProcessor的代理对象webSecurity = objectPostProcessor.postProcess(new WebSecurity(objectPostProcessor));//从spring容器中获得所有配置的WebSecurityConfigurerAdapter的类//WebSecurityConfigurerAdapter是我们配置的springSecurity要继承的类//调用他的apply方法for (SecurityConfigurer<Filter, WebSecurity> webSecurityConfigurer : webSecurityConfigurers) {//将WebSecurityConfigurerAdapter放到一个集合LinkedHashMap中webSecurity.apply(webSecurityConfigurer);}this.webSecurityConfigurers = webSecurityConfigurers;}

代码分析
上面代码会创建一个 AutowireBeanFactoryObjectPostProcessor的代理类 WebSecurity
WebSecurity这个类可以向spring容器添加对象,同时还维护着一个LinkedHashMap用来存储所有的WebSecurityConfigurerAdapterWebSecurityConfigurerAdapter是配置springSecurity要继承的类

接下来看这个类org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration
代码如下

@Bean(name = "springSecurityFilterChain")
public Filter springSecurityFilterChain() throws Exception {boolean hasConfigurers = webSecurityConfigurers != null&& !webSecurityConfigurers.isEmpty();if (!hasConfigurers) {//通过AutowireBeanFactoryObjectPostProcessor向spring容器注册WebSecurityConfigurerAdapterWebSecurityConfigurerAdapter adapter = objectObjectPostProcessor.postProcess(new WebSecurityConfigurerAdapter() {});webSecurity.apply(adapter);}//调用return webSecurity.build();
}

代码分析
上面代码会通过AutowireBeanFactoryObjectPostProcessor向spring容器注册一个对象WebSecurityConfigurerAdapter,然后将WebSecurityConfigurerAdapter存储到webSecurity中,
然后调用webSecuritybuild方法,执行代码如下

protected final O doBuild() throws Exception {//configurers 是webSecurity中存储WebSecurityConfigurerAdapter的LinkedHashMapsynchronized (configurers) {//通过枚举修改状态buildState = BuildState.INITIALIZING;//空方法 用于扩展beforeInit();//调用configurers集合中所有对象的init方法//当前集合中只有一个对象 WebSecurityConfigurerAdapterinit();buildState = BuildState.CONFIGURING;beforeConfigure();//调用configurers集合中所有对象的configure方法configure();buildState = BuildState.BUILDING;O result = performBuild();buildState = BuildState.BUILT;return result;}
}

接下来依次分析 init()beforeConfigure()configure()performBuild()方法,WebSecurityConfigurerAdapter

此部分代码比较多分部分析,代码如下

public void init(final WebSecurity web) throws Exception {//创建一个HttpSecurityfinal HttpSecurity http = getHttp();web.addSecurityFilterChainBuilder(http).postBuildAction(() -> {FilterSecurityInterceptor securityInterceptor = http.getSharedObject(FilterSecurityInterceptor.class);//给WebSecurity设置一个拦截器web.securityInterceptor(securityInterceptor);});protected final HttpSecurity getHttp() throws Exception {//首先创建DefaultAuthenticationEventPublisher对象然后将这个对象添加到spring容器中//此对象维护着一个exceptionMappings对象,存储异常和ApplicationEventDefaultAuthenticationEventPublisher eventPublisher = objectPostProcessor.postProcess(new DefaultAuthenticationEventPublisher());//将eventPublisher给localConfigureAuthenticationBldr代理//localConfigureAuthenticationBldr 也就是 AuthenticationManagerBuilder对象localConfigureAuthenticationBldr.authenticationEventPublisher(eventPublisher);AuthenticationManager authenticationManager = authenticationManager();authenticationBuilder.parentAuthenticationManager(authenticationManager);authenticationBuilder.authenticationEventPublisher(eventPublisher);Map<Class<?>, Object> sharedObjects = createSharedObjects();//创建http对象,其中FilterComparator中存储了32个过滤器 http = new HttpSecurity(objectPostProcessor, authenticationBuilder,sharedObjects);if (!disableDefaults) {// 往HttpSecurity添加一些列的 配置类//CsrfConfigurer//ExceptionHandlingConfigurer//HeadersConfigurer//SessionManagementConfigurer//SecurityContextConfigurer//RequestCacheConfigurer//AnonymousConfigurer//ServletApiConfigurer//DefaultLoginPageConfigurer//LogoutConfigurerhttp.csrf().and().addFilter(new WebAsyncManagerIntegrationFilter()).exceptionHandling().and().headers().and().sessionManagement().and().securityContext().and().requestCache().and().anonymous().and().servletApi().and().apply(new DefaultLoginPageConfigurer<>()).and().logout();ClassLoader classLoader = this.context.getClassLoader();//添加一些默认配置List<AbstractHttpConfigurer> defaultHttpConfigurers =SpringFactoriesLoader.loadFactories(AbstractHttpConfigurer.class, classLoader);//添加一些默认配置for (AbstractHttpConfigurer configurer : defaultHttpConfigurers) {http.apply(configurer);}}//调用自己配置的 configure方法,添加一些Configurerconfigure(http);return http;}protected AuthenticationManager authenticationManager() throws Exception {//这里仅仅用一个标志位不用锁 也不会线程不安全//因为build 方法中通过  //if(AtomicBoolean.compareAndSet(false, true)){}if (!authenticationManagerInitialized) {//调用配置的configure方法//方法中我们给 provider的 UserDetailsService,passwordEncoder 成员变量赋值//同时添加DaoAuthenticationConfigurer 对象configure(localConfigureAuthenticationBldr);if (disableLocalConfigureAuthenticationBldr) {//如果我们没有重写configure方法则调用这里逻辑authenticationManager = authenticationConfiguration.getAuthenticationManager();}else {//localConfigureAuthenticationBldr 也就是 AuthenticationManagerBuilder对象//AuthenticationManagerBuilder中的configurers中只有一个对象DaoAuthenticationConfigurer//调用 DaoAuthenticationConfigurer 的doBuild方法//方法中会通过包装创建一个ProviderManagerauthenticationManager = localConfigureAuthenticationBldr.build();}authenticationManagerInitialized = true;}return authenticationManager;}private void configure() throws Exception {Collection<SecurityConfigurer<O, B>> configurers = getConfigurers();//循环调用所有配置类的方法//有的configurer中的configure方法会添加拦截器for (SecurityConfigurer<O, B> configurer : configurers) {configurer.configure((B) this);}}protected Filter performBuild() throws Exception {Assert.state(!securityFilterChainBuilders.isEmpty(),() -> "At least one SecurityBuilder<? extends SecurityFilterChain> needs to be specified. "+ "Typically this done by adding a @Configuration that extends WebSecurityConfigurerAdapter. "+ "More advanced users can invoke "+ WebSecurity.class.getSimpleName()+ ".addSecurityFilterChainBuilder directly");int chainSize = ignoredRequests.size() + securityFilterChainBuilders.size();List<SecurityFilterChain> securityFilterChains = new ArrayList<>(chainSize);for (RequestMatcher ignoredRequest : ignoredRequests) {securityFilterChains.add(new DefaultSecurityFilterChain(ignoredRequest));}//securityFilterChainBuilder中存储所有的 HttpSecurityfor (SecurityBuilder<? extends SecurityFilterChain> securityFilterChainBuilder : securityFilterChainBuilders) {//在方法中循环遍历所有HttpSecurity中configurers //configurers 是webSecurity中存储WebSecurityConfigurerAdapter的LinkedHashMap//调用所有配置类的configurer 的 init configure 方法//securityFilterChains.add(securityFilterChainBuilder.build());}//通过FilterChainProxy对securityFilterChains进行包装FilterChainProxy filterChainProxy = new FilterChainProxy(securityFilterChains);if (httpFirewall != null) {filterChainProxy.setFirewall(httpFirewall);}filterChainProxy.afterPropertiesSet();Filter result = filterChainProxy;postBuildAction.run();return result;}
}

上面代码通过CsrfConfigurer、ExceptionHandlingConfigurer、HeadersConfigurer、SessionManagementConfigurer、SecurityContextConfigurer、RequestCacheConfigurer、AnonymousConfigurer 、ServletApiConfigurer、DefaultLoginPageConfigurer、LogoutConfigurer 等对象的 configure 方法 添加过滤器,我们配置对应的Configurer对象就能修改过滤器要拦截的内容,过滤器如下

WebAsyncManagerIntegrationFilter

SecurityContextPersistenceFilter

HeaderWriterFilter

CsrfFilter

LogoutFilter

MyTokenFilter

UsernamePasswordAuthenticationFilter

DefaultLoginPageGeneratingFilter

DefaultLogoutPageGeneratingFilter

RequestCacheAwareFilter

SecurityContextHolderAwareRequestFilter

AnonymousAuthenticationFilter

SessionManagementFilter

ExceptionTranslationFilter

FilterSecurityInterceptor

志宇-springSecurty相关推荐

  1. 一周年感谢信 | 黑萤科技赖志宇:志同者将道合一处

    一周年感谢信 | 黑萤科技赖志宇:志同者将道合一处 赖志宇 IPFS黑萤科技 1周前 亲爱的萤火虫: 你们好! 自2018年4月30日公司的营业执照下来,黑萤科技已满一周年. 这一年,我们经历过高光时 ...

  2. 志宇-RocketMQ学习

    RocketMQ RocketMQ安装 RocketMQ-console安装 RocketMQ简单使用 RabbitMQ核心概念 消息发送状态(返回对象中的枚举类型有4种) 重试次数 RocketMQ ...

  3. 志宇-RabbitMQ学习

    RabbitMQ RabbitMQ安装 RabbitMQ使用 RabbitMQ发送消息步骤图 公平消费和消息可靠性传递 防止重复消费 有序消费 消息堆积怎么处理 spring集成RabbitMQ使用 ...

  4. 志宇-Nginx学习

    Nginx nginx如何去处理一个请求 Nginx可用性探测 Nginx搭建静态资源服务器 Nginx配置https服务 Nginx流量统计 Nginx黑白名单拦截 异常兜底返回 OpenResty ...

  5. 志宇-Jenkins学习

    Jenkins 部署Jenkins 访问Jenkins Jenkins安装插件 Jenkins配置 配置JDK 配置MAVEN 配置Git 配置邮箱 Jenkins配置GitHub Jenkins授权 ...

  6. 志宇-nexus学习

    nexus /ˈneksəs/ 环境安装 nexus安装 nexus 使用 登录nexus 创建一个公司的私有仓库,然后添加到私服的中央仓库中 私服代理配置成阿里云镜像 maven加载setting文 ...

  7. 志宇-linux命令

    linux命令备忘录 linux系统登录远程服务器 windws查看端口号占用的pid linux 传输文件 Linux 定时任务 linux文本文件查看 动态查看文件最后100行 查看文件最后几页 ...

  8. 志宇-springBoot启动

    springBoot是如何启动的 springBoot的部署 通过maven插件执行install命令,将项目打包成一个jar文件在target目录下 执行jar包中的内容, 在服务器上执行java ...

  9. @Configuration志宇分析

    @Configuration 原理 一.执行这个注解的位置ConfigurationClassPostProcessor refresh();invokeBeanFactoryPostProcesso ...

最新文章

  1. 【数据结构】顺序表的应用(3)(C语言)
  2. Python学习笔记(八)—使用正则获取网页中所需要的信息。
  3. eclipse中测试Hibernate异常报 ORA-00926: 缺失 VALUES 关键字
  4. 【CyberSecurityLearning 76】DC系列之DC-7渗透测试(Drupal)
  5. iOS开发(2)UILabel学习
  6. JavaOne 2012:非阻塞数据结构如何工作?
  7. 硬核|定时任务的10种实现方案,满足你的不同需求!
  8. 30 个 Python 的最佳实践、小贴士和技巧,不可错过哟!
  9. html+css面试题 行内元素padding和margin
  10. ant使用ftp上传数据时配置的一个报错问题
  11. Memcached原理与应用
  12. sv_labs学习笔记——sv_lab5_下(System Verilog)
  13. 服务器lnixs系统,Navicat for MySQL v12.1.19 强大的数据库管理和开发工具 _ 黑苹果乐园...
  14. 教你怎么搞定P2P终结者的网速限制
  15. C语言模拟实现memcmp函数
  16. idea创建SpringBoot工程
  17. 免费翻译英文文献自动生成PDF双语文档小技巧
  18. 虚幻4实战 贪吃蛇制作
  19. 手机端网页尺寸html,手机端网页设计尺寸_html/css_WEB-ITnose
  20. 团队建设的一些思考和实践

热门文章

  1. 电路分析第一章 电路及其基本概念
  2. 海淘 Google Nexus4 历程
  3. JavaScript之正则表达式的使用方法详细介绍
  4. POJ1815 Friendship
  5. 如何做好一个程序员——摘自水木清华BBS
  6. LiveVISGAT1400视图库服务-支持海康大华华为宇视天地伟业等设备视图库接入使用说明
  7. 如何高效地准备技术面试?
  8. 从零开始仿写一个BiliBili客户端之编译ijkplayer
  9. 【企业实践案例】- 滴滴大数据安全权限实践
  10. netflix 会员看整部_Netflix –您租了多少部电影