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

spring-security原理与应用系列:总体流程

目录

1.简单的使用示例

2.大致的流程

EnableWebSecurity

WebSecurityConfiguration

AutowiredWebSecurityConfigurersIgnoreParents

小结


1.简单的使用示例

        首先,新建一个config包用于存放spring-security通用配置;然后,新建一个WebSecurityConfig类,使其继承WebSecurityConfigurerAdapter。

        然后,给WebSecutiryConfig类中加上@EnableWebSecurity 注解后,这样便会自动被 Spring发现并注册。

@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
   @Override
   protected void configure(HttpSecurity http) throws Exception {
      http.authorizeHttpRequests()

            .anyRequest().authenticated()

            .and()

            .formLogin(form -> form

                .loginPage("/myLogin.html")

                .permitAll())

            .logout(logout -> logout

                .permitAll())

            .csrf().disable();

        return http.build();

}

        现在重启服务,应用新的安全配置。在下次访问localhost:8080时,系统会要求我们进行表单认证。我们访问的地址会自动跳转到localhost:8080/myLogin.html,只要输入正确的用户名和密码便可跳转回原访问地址。

2.大致的流程

        一般在使用 Spring Security 框架时,我们会自定义一个配置类,配置类加上 @EnableWebSecurity 注解,重新启动程序,一个使用了安全框架的项目就起来了。

        点击自定义配置类上添加的 @EnableWebSecurity,如下所示:

EnableWebSecurity

@Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME)
@Target(value = { java.lang.annotation.ElementType.TYPE })
@Documented
@Import({ WebSecurityConfiguration.class, SpringWebMvcImportSelector.class })
@EnableGlobalAuthentication
@Configuration
public @interface EnableWebSecurity {
   /**
    * Controls debugging support for Spring Security. Default is false.
    * @return if true, enables debug support with Spring Security
    */
   boolean debug() default false;
}

        重点关注 @Import 导入的类 WebSecurityConfiguration 。

        点击@Import 导入的类 WebSecurityConfiguration,如下所示:

WebSecurityConfiguration

    在这里,发现类中定义了很多Bean,其中就有跟安全管理相关的核心过滤器springSecurityFilterChain。

@Configuration
public class WebSecurityConfiguration implements ImportAware, BeanClassLoaderAware {

... ...

@Bean(name = AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME)
public Filter springSecurityFilterChain() throws Exception {
   boolean hasConfigurers = webSecurityConfigurers != null
         && !webSecurityConfigurers.isEmpty();
   if (!hasConfigurers) {
      WebSecurityConfigurerAdapter adapter = objectObjectPostProcessor
            .postProcess(new WebSecurityConfigurerAdapter() {
            });
      webSecurity.apply(adapter);
   }
   return webSecurity.build();
}

        这个方法返回的是Filter,说明这个Bean是一个过滤器。

        webSecurity.build():这行代码说明这个Filter是通过webSecurity创建的,而且webSecurity是通过建造者模式来构建Filter对象的。后续再深入了解webSecurity建造者的构建过程。

        webSecurity.apply(adapter):这行代码是构建者webSecurity使用一个配置器。hasConfigurers为空时,new一个WebSecurityConfigurerAdapter对象,不为空时,查看如下的setFilterChainProxySecurityConfigurer方法。

@Autowired(required = false)
public void setFilterChainProxySecurityConfigurer(ObjectPostProcessor<Object> objectPostProcessor,   @Value("#{@autowiredWebSecurityConfigurersIgnoreParents.getWebSecurityConfigurers()}") List<SecurityConfigurer<Filter, WebSecurity>> webSecurityConfigurers)
      throws Exception {
   webSecurity = objectPostProcessor
         .postProcess(new WebSecurity(objectPostProcessor));
   if (debugEnabled != null) {
      webSecurity.debug(debugEnabled);
   }
   Collections.sort(webSecurityConfigurers, AnnotationAwareOrderComparator.INSTANCE);
   Integer previousOrder = null;
   Object previousConfig = null;
   for (SecurityConfigurer<Filter, WebSecurity> config : webSecurityConfigurers) {
      Integer order = AnnotationAwareOrderComparator.lookupOrder(config);
      if (previousOrder != null && previousOrder.equals(order)) {
         ... ...

      }
      previousOrder = order;
      previousConfig = config;
   }
   for (SecurityConfigurer<Filter, WebSecurity> webSecurityConfigurer : webSecurityConfigurers)   

   {
      webSecurity.apply(webSecurityConfigurer);
   }
   this.webSecurityConfigurers = webSecurityConfigurers;
}

       在这里,通过autowiredWebSecurityConfigurersIgnoreParents.getWebSecurityConfigurers()获取配置器,然后建造者webSecurity再使用这些配置器。

     点击autowiredWebSecurityConfigurersIgnoreParents.getWebSecurityConfigurers(),如下所示:

AutowiredWebSecurityConfigurersIgnoreParents

final class AutowiredWebSecurityConfigurersIgnoreParents {

... ...

public List<SecurityConfigurer<Filter, WebSecurity>> getWebSecurityConfigurers() {
   List<SecurityConfigurer<Filter, WebSecurity>> webSecurityConfigurers = new ArrayList<SecurityConfigurer<Filter, WebSecurity>>();
   Map<String, WebSecurityConfigurer> beansOfType = beanFactory
         .getBeansOfType(WebSecurityConfigurer.class);
   for (Entry<String, WebSecurityConfigurer> entry : beansOfType.entrySet()) {
      webSecurityConfigurers.add(entry.getValue());
   }
   return webSecurityConfigurers;
}

       在这里,通过beanFactory获取WebSecurityConfigurer实例,这些实例正是我们使用spring-security所自定义的配置类WebSecurityConfig。

小结

        整个流程主要由建造者和配置器构成,在服务启动时就是通过配置器对建造者所要构建的对象进行配置,配置完成再由建造者构建出核心过滤器springSecurityFilterChain。


http://www.kler.cn/a/600140.html

相关文章:

  • RabbitMQ的高级特性介绍(二)
  • Transformer 通关秘籍2:利用 BERT 将文本 token 化
  • 基于微信小程序的短文写作竞赛管理系统
  • Windows桌面采集技术
  • 【Matlab】串口通信(serialport对象,读写、回调、删除等)
  • Java-腾讯云短信模板兼容阿里云短信模板-短信模板参数生成
  • 【JavaWeb学习Day27】
  • Windows下编译安装Qt5.15.0指南
  • 23种设计模式中的策略模式
  • Xshell、Xsftp、Xmanager中文版安装包及使用教程
  • Redis Sentinel(哨兵模式)高可用性解决方案
  • hackmyvm-Icecream
  • CSS圣杯布局与双飞翼布局
  • Redisson分布式锁(超时释放及锁续期)
  • AI进化论:从图灵测试到智能革命的临界点
  • Python学习第二十三天
  • Flink CEP:复杂事件处理详解
  • 架构思维:从代码实现到系统思维的进阶之路
  • 基于ConcurrentHashMap+Redisson的轻量级分布式锁架构设计与工业级实现
  • [特殊字符] C++ 常见 Socket 错误与优化指南