当前位置: 首页 > news >正文

09 - spring security加载流程

spring security加载流程

文档

  1. 00 - spring security框架使用
  2. 01 - spring security自定义登录页面
  3. 02 - spring security基于配置文件及内存的账号密码
  4. 03 - spring security自定义登出页面
  5. 04 - spring security关闭csrf攻击防御
  6. 05 - spring security权限控制
  7. 06 - spring security角色和权限设置
  8. 07 - spring security基于数据库的账号密码
  9. 08 - spring security基于jdbc的账号密码

说明

  1. spring security版本:3.2.0

spring security加载流程

  1. 创建HttpSecurity对象,此处用的是@Scope("prototype")注解,在自定义配置中,操作的就是该对象

    //
    // Source code recreated from a .class file by IntelliJ IDEA
    // (powered by FernFlower decompiler)
    //package org.springframework.security.config.annotation.web.configuration;@Configuration(proxyBeanMethods = false
    )
    class HttpSecurityConfiguration {// ...@Bean({"org.springframework.security.config.annotation.web.configuration.HttpSecurityConfiguration.httpSecurity"})@Scope("prototype")HttpSecurity httpSecurity() throws Exception {LazyPasswordEncoder passwordEncoder = new LazyPasswordEncoder(this.context);AuthenticationManagerBuilder authenticationBuilder = new DefaultPasswordEncoderAuthenticationManagerBuilder(this.objectPostProcessor, passwordEncoder);authenticationBuilder.parentAuthenticationManager(this.authenticationManager());authenticationBuilder.authenticationEventPublisher(this.getAuthenticationEventPublisher());HttpSecurity http = new HttpSecurity(this.objectPostProcessor, authenticationBuilder, this.createSharedObjects());WebAsyncManagerIntegrationFilter webAsyncManagerIntegrationFilter = new WebAsyncManagerIntegrationFilter();webAsyncManagerIntegrationFilter.setSecurityContextHolderStrategy(this.securityContextHolderStrategy);http.csrf(Customizer.withDefaults()).addFilter(webAsyncManagerIntegrationFilter).exceptionHandling(Customizer.withDefaults()).headers(Customizer.withDefaults()).sessionManagement(Customizer.withDefaults()).securityContext(Customizer.withDefaults()).requestCache(Customizer.withDefaults()).anonymous(Customizer.withDefaults()).servletApi(Customizer.withDefaults()).apply(new DefaultLoginPageConfigurer());http.logout(Customizer.withDefaults());this.applyCorsIfAvailable(http);this.applyDefaultConfigurers(http);return http;}}
    
  2. 默认的SecurityFilterChain对象

    @Configuration(proxyBeanMethods = false
    )
    @ConditionalOnWebApplication(type = Type.SERVLET
    )
    class SpringBootWebSecurityConfiguration {// ...@Configuration(proxyBeanMethods = false)@ConditionalOnDefaultWebSecuritystatic class SecurityFilterChainConfiguration {SecurityFilterChainConfiguration() {}@Bean@Order(2147483642)SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {http.authorizeHttpRequests((requests) -> {((AuthorizeHttpRequestsConfigurer.AuthorizedUrl)requests.anyRequest()).authenticated();});http.formLogin(Customizer.withDefaults());http.httpBasic(Customizer.withDefaults());return (SecurityFilterChain)http.build();}}
    }
    
  3. 上面是默认的SecurityFilterChain类型的Bean,实际使用中,我们会自定义SecurityFilterChain类型的Bean,当我们自定义时,上面的默认配置会失效

  4. 定义SecurityFilterChain类型的Bean时,会注入HttpSecurity对象,就是在最开始的流程中创建的,在调用HttpSecurity以下方法时,会创建更多其它相关的对象

    1. http.formLogin(Customizer.withDefaults());,1️⃣
    2. http.build(),6️⃣
  5. 接口:SecurityBuilder

    1. 实现类:AbstractSecurityBuilder

      1. 方法:public final O build() throws Exception,7️⃣

        public final O build() throws Exception {if (this.building.compareAndSet(false, true)) {this.object = this.doBuild();return this.object;} else {throw new AlreadyBuiltException("This object has already been built");}
        }
        
      2. 子类:AbstractConfiguredSecurityBuilder

        1. 属性:private final LinkedHashMap<Class<? extends SecurityConfigurer<O, B>>, List<SecurityConfigurer<O, B>>> configurers;

        2. 方法:protected final O doBuild() throws Exception,8️⃣

          protected final O doBuild() throws Exception {synchronized(this.configurers) {this.buildState = AbstractConfiguredSecurityBuilder.BuildState.INITIALIZING;this.beforeInit();this.init();this.buildState = AbstractConfiguredSecurityBuilder.BuildState.CONFIGURING;this.beforeConfigure();this.configure();this.buildState = AbstractConfiguredSecurityBuilder.BuildState.BUILDING;O result = this.performBuild();this.buildState = AbstractConfiguredSecurityBuilder.BuildState.BUILT;return result;}
          }
          

          说明:

          1. 关注this.beforeConfigure();this.configure();方法
        3. 方法:private void configure(),🔟

          private void configure() throws Exception {Collection<SecurityConfigurer<O, B>> configurers = this.getConfigurers();Iterator var2 = configurers.iterator();while(var2.hasNext()) {SecurityConfigurer<O, B> configurer = (SecurityConfigurer)var2.next();configurer.configure(this);}}
          

          说明:这里我们关注FormLoginConfigurer

        4. 子类:HttpSecurity

          1. 方法:public HttpSecurity formLogin(Customizer<FormLoginConfigurer<HttpSecurity>> formLoginCustomizer) throws Exception,2️⃣

            public HttpSecurity formLogin(Customizer<FormLoginConfigurer<HttpSecurity>> formLoginCustomizer) throws Exception {formLoginCustomizer.customize((FormLoginConfigurer)this.getOrApply(new FormLoginConfigurer()));return this;
            }
            

            说明:

            1. 实际使用中,我们会在自定义SecurityFilterChain类型的Bean时,注入HttpSecurity对象,并且调用formLogin方法
            2. formLogin方法的入参formLoginCustomizer,一般会以匿名内部类的方式传入,该匿名内部类重写customize方法
            3. customize方法的入参为FormLoginConfigurer对象,所以在我们自定义的配置中,实际操作的是FormLoginConfigurer对象,该对象来自于(FormLoginConfigurer)this.getOrApply(new FormLoginConfigurer())
            4. (FormLoginConfigurer)this.getOrApply(new FormLoginConfigurer())会向configurers属性中添加一个键值对this.configurers.put(clazz, configs);configsList类型,new FormLoginConfigurer()是其中的元素
          2. 方法:protected void beforeConfigure() throws Exception,9️⃣

            protected void beforeConfigure() throws Exception {if (this.authenticationManager != null) {this.setSharedObject(AuthenticationManager.class, this.authenticationManager);} else {ObservationRegistry registry = this.getObservationRegistry();AuthenticationManager manager = (AuthenticationManager)this.getAuthenticationRegistry().build();if (!registry.isNoop() && manager != null) {this.setSharedObject(AuthenticationManager.class, new ObservationAuthenticationManager(registry, manager));} else {this.setSharedObject(AuthenticationManager.class, manager);}}}
            

            说明:此处会向sharedObjects属性中添加一个键值对this.setSharedObject(AuthenticationManager.class, manager);,该managerProviderManager对象

  6. 接口:SecurityConfigurer

    1. 实现类:SecurityConfigurerAdapter

      1. 子类:AbstractHttpConfigurer

        1. 子类:AbstractAuthenticationFilterConfigurer

          1. 属性:private F authFilter;

            说明:authFilter属性的值是UsernamePasswordAuthenticationFilter对象

          2. 构造方法,4️⃣

            protected AbstractAuthenticationFilterConfigurer(F authenticationFilter, String defaultLoginProcessingUrl) {this();this.authFilter = authenticationFilter;if (defaultLoginProcessingUrl != null) {this.loginProcessingUrl(defaultLoginProcessingUrl);}}
            

            说明:

            1. 这里的authenticationFilterUsernamePasswordAuthenticationFilter对象
            2. UsernamePasswordAuthenticationFilter对象会加入到FormLoginConfigurer对象的authFilter属性中
          3. 方法:public void configure(B http),1️⃣1️⃣

            public void configure(B http) throws Exception {PortMapper portMapper = (PortMapper)http.getSharedObject(PortMapper.class);if (portMapper != null) {this.authenticationEntryPoint.setPortMapper(portMapper);}RequestCache requestCache = (RequestCache)http.getSharedObject(RequestCache.class);if (requestCache != null) {this.defaultSuccessHandler.setRequestCache(requestCache);}this.authFilter.setAuthenticationManager((AuthenticationManager)http.getSharedObject(AuthenticationManager.class));this.authFilter.setAuthenticationSuccessHandler(this.successHandler);this.authFilter.setAuthenticationFailureHandler(this.failureHandler);if (this.authenticationDetailsSource != null) {this.authFilter.setAuthenticationDetailsSource(this.authenticationDetailsSource);}SessionAuthenticationStrategy sessionAuthenticationStrategy = (SessionAuthenticationStrategy)http.getSharedObject(SessionAuthenticationStrategy.class);if (sessionAuthenticationStrategy != null) {this.authFilter.setSessionAuthenticationStrategy(sessionAuthenticationStrategy);}RememberMeServices rememberMeServices = (RememberMeServices)http.getSharedObject(RememberMeServices.class);if (rememberMeServices != null) {this.authFilter.setRememberMeServices(rememberMeServices);}SecurityContextConfigurer securityContextConfigurer = (SecurityContextConfigurer)http.getConfigurer(SecurityContextConfigurer.class);if (securityContextConfigurer != null && securityContextConfigurer.isRequireExplicitSave()) {SecurityContextRepository securityContextRepository = securityContextConfigurer.getSecurityContextRepository();this.authFilter.setSecurityContextRepository(securityContextRepository);}this.authFilter.setSecurityContextHolderStrategy(this.getSecurityContextHolderStrategy());F filter = (AbstractAuthenticationProcessingFilter)this.postProcess(this.authFilter);http.addFilter(filter);
            }
            

            说明:this.authFilter.setAuthenticationManager((AuthenticationManager)http.getSharedObject(AuthenticationManager.class));方法中,(AuthenticationManager)http.getSharedObject(AuthenticationManager.class)获取到的是ProviderManager对象,该对象是在HttpSecurity类的beforeConfigure()方法中设置的

          4. 子类:FormLoginConfigurer

            1. 构造方法,3️⃣

              public FormLoginConfigurer() {super(new UsernamePasswordAuthenticationFilter(), (String)null);this.usernameParameter("username");this.passwordParameter("password");
              }
              

              说明:该FormLoginConfigurer对象会加入到HttpSecurity对象的configurers属性中

  7. 抽象类:AbstractAuthenticationProcessingFilter

    1. 属性:private AuthenticationManager authenticationManager;

    2. 方法:public void setAuthenticationManager(AuthenticationManager authenticationManager),1️⃣2️⃣

      public void setAuthenticationManager(AuthenticationManager authenticationManager) {this.authenticationManager = authenticationManager;
      }
      

      说明:该authenticationManagerProviderManager对象,会加入到UsernamePasswordAuthenticationFilter对象的authenticationManager属性中

    3. 子类:UsernamePasswordAuthenticationFilter

      1. 构造方法,5️⃣

        public UsernamePasswordAuthenticationFilter() {super(DEFAULT_ANT_PATH_REQUEST_MATCHER);
        }
        

        说明:该UsernamePasswordAuthenticationFilter对象会加入到FormLoginConfigurer对象的authFilter属性中

总结

// 伪代码
ProviderManager manager = new ProviderManager();UsernamePasswordAuthenticationFilter usernamePasswordAuthenticationFilter = new UsernamePasswordAuthenticationFilter();
usernamePasswordAuthenticationFilter.authenticationManager = manager;FormLoginConfigurer formLoginConfigurer = new FormLoginConfigurer();
formLoginConfigurer.authFilter = usernamePasswordAuthenticationFilter;HttpSecurity httpSecurity = new HttpSecurity();
httpSecurity.configurers.put(FormLoginConfigurer.class, Arrays.asList(formLoginConfigurer));
httpSecurity.sharedObject.put(AuthenticationManager.class, manager);

如有不对,欢迎指正!

http://www.dtcms.com/a/395813.html

相关文章:

  • 【大前端】Android:读取剪切板与禁用剪切板复制功能(完整指南)
  • 第18讲 机器学习与深度学习
  • 数据结构 05(线性:栈和队列)
  • RAG系统嵌入模型怎么选?选型策略和踩坑指南
  • 机器学习 vs. 动力学模型,Ai2 最新研究:仅需 2 分钟,ACE2 可完成一次 4 个月季节预报
  • RNN循环神经网络详解
  • 【Nginx开荒攻略】深入解析Nginx进程管理与信号控制:从原理到实战
  • MySQL与Redis面试问题详解
  • 鸿蒙Next IPC Kit详解:构建高效进程间通信的完整指南
  • 【开题答辩全过程】以 基于springboot的高校疫情防控系统为例,包含答辩的问题和答案
  • Centos7 命令行使用nmcli重置网络配置
  • 如何计算sequence粒度的负载均衡损失
  • 学财税大数据应用,需要考CPA/税务师吗?
  • RAG全栈技术——文档加载器
  • 如何理解Service Mesh(服务网格)
  • android9适配camera gc02m1
  • 【十天成长计划】BoostKit初级班 开班啦!——陪伴式学习,阶梯式成长
  • 【图文详解】强化学习核心框架、数学基础、分类、应用场景
  • Rust简介
  • golang和rust内存分配策略
  • 简历项目之无人机图像目标识别
  • pantherx2 armbian librga-rockchip librga.so 编译安装方法
  • 【精品资料鉴赏】189页工程车辆集团数字化转型SAP解决方案
  • 算法 --- 多源 BFS
  • 15.Linux 硬盘分区管理
  • 2.UE-准备环境(二)-下载虚幻引擎源码和搞成vs项目并使用vs打开
  • G-Star公益行获评CCF优秀技术公益案例,用开源技术传递善意
  • 文化赋能・创意西宁 西宁传媒行业创业发展沙龙成功举办 探索本土企业升级新路径
  • TDengine 与 MYSQL 的差异总结
  • Mysql杂志(二十一)——Hash索引和二叉搜索树、AVL树