一、Spring Boot集成Spring Security之自动装配

打印 上一主题 下一主题

主题 946|帖子 946|积分 2838

二、实现功能及软件版本说明


  • 使用Spring Boot集成Spring Security实现Servlet项目的安全个性化配置
  • Spring Boot版本:2.7.18
  • Spring Security版本:5.7.11
三、创建Spring Boot项目


  • 创建Spring Boot项目,目次结构如下

  • 引入Spring Security包,完整pom.xml如下
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3.          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  4.     <modelVersion>4.0.0</modelVersion>
  5.     <parent>
  6.         <groupId>org.springframework.boot</groupId>
  7.         <artifactId>spring-boot-starter-parent</artifactId>
  8.         <version>2.7.18</version>
  9.         <relativePath/>
  10.     </parent>
  11.     <groupId>com.yu</groupId>
  12.     <artifactId>spring-boot-security2-demo</artifactId>
  13.     <version>0.0.1-SNAPSHOT</version>
  14.     <name>spring-boot-security2-demo</name>
  15.     <description>Spring Boot集成Spring Security样例</description>
  16.     <properties>
  17.         <java.version>8</java.version>
  18.     </properties>
  19.     <dependencies>
  20.         <dependency>
  21.             <groupId>org.springframework.boot</groupId>
  22.             <artifactId>spring-boot-starter-web</artifactId>
  23.         </dependency>
  24.         <dependency>
  25.             <groupId>org.springframework.boot</groupId>
  26.             <artifactId>spring-boot-starter-security</artifactId>
  27.         </dependency>
  28.     </dependencies>
  29. </project>
复制代码
四、查看自动装配配置类


  • 查看Security Servlet相关自动装配配置类

五、自动装配配置类之SecurityAutoConfiguration

1、部分源码
  1. @AutoConfiguration
  2. @ConditionalOnClass(DefaultAuthenticationEventPublisher.class)
  3. @EnableConfigurationProperties(SecurityProperties.class)
  4. @Import({ SpringBootWebSecurityConfiguration.class, SecurityDataConfiguration.class })
  5. public class SecurityAutoConfiguration {
  6.         @Bean
  7.         @ConditionalOnMissingBean(AuthenticationEventPublisher.class)
  8.         public DefaultAuthenticationEventPublisher authenticationEventPublisher(ApplicationEventPublisher publisher) {
  9.                 return new DefaultAuthenticationEventPublisher(publisher);
  10.         }
  11. }
复制代码
2、紧张作用


  • 导入SpringBootWebSecurityConfiguration
3、SpringBootWebSecurityConfiguration

1)、部分源码
  1. @Configuration(proxyBeanMethods = false)
  2. @ConditionalOnWebApplication(type = Type.SERVLET)
  3. class SpringBootWebSecurityConfiguration {
  4.         @Configuration(proxyBeanMethods = false)
  5.         @ConditionalOnDefaultWebSecurity
  6.         static class SecurityFilterChainConfiguration {
  7.                 @Bean
  8.                 @Order(SecurityProperties.BASIC_AUTH_ORDER)
  9.                 SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
  10.                         http.authorizeRequests().anyRequest().authenticated();
  11.                         http.formLogin();
  12.                         http.httpBasic();
  13.                         return http.build();
  14.                 }
  15.         }
  16.         @Configuration(proxyBeanMethods = false)
  17.         @ConditionalOnMissingBean(name = BeanIds.SPRING_SECURITY_FILTER_CHAIN)
  18.         @ConditionalOnClass(EnableWebSecurity.class)
  19.         @EnableWebSecurity
  20.         static class WebSecurityEnablerConfiguration {
  21.         }
  22. }
复制代码
2)、紧张作用


  • 默认Security配置(Spring容器中没有SecurityFilterChain和WebSecurityConfigurerAdapter)时,向Spring容器中注入默认过滤器链,即用户没有自界说过滤器链时,生成默认过滤器链

  • Spring容器中不存在名称为springSecurityFilterChain对象时,启用WebSecurity,即用户未表现的启用WebSecurity时,隐式的启用WebSecurity

4、@EnableWebSecurity

1)、部分源码
  1. @Retention(RetentionPolicy.RUNTIME)
  2. @Target(ElementType.TYPE)
  3. @Documented
  4. @Import({ WebSecurityConfiguration.class, SpringWebMvcImportSelector.class, OAuth2ImportSelector.class,
  5.                 HttpSecurityConfiguration.class })
  6. @EnableGlobalAuthentication
  7. @Configuration
  8. public @interface EnableWebSecurity {
  9.         /**
  10.          * Controls debugging support for Spring Security. Default is false.
  11.          * @return if true, enables debug support with Spring Security
  12.          */
  13.         boolean debug() default false;
  14. }
复制代码
2)、紧张作用


  • 导入WebSecurityConfiguration
  • 导入HttpSecurityConfiguration
5、WebSecurityConfiguration

1)、部分源码
  1. @Configuration(proxyBeanMethods = false)
  2. public class WebSecurityConfiguration implements ImportAware, BeanClassLoaderAware {
  3. @Bean(name = AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME)
  4.         public Filter springSecurityFilterChain() throws Exception {
  5.                 boolean hasConfigurers = this.webSecurityConfigurers != null && !this.webSecurityConfigurers.isEmpty();
  6.                 boolean hasFilterChain = !this.securityFilterChains.isEmpty();
  7.                 Assert.state(!(hasConfigurers && hasFilterChain),
  8.                                 "Found WebSecurityConfigurerAdapter as well as SecurityFilterChain. Please select just one.");
  9.                 if (!hasConfigurers && !hasFilterChain) {
  10.                         WebSecurityConfigurerAdapter adapter = this.objectObjectPostProcessor
  11.                                         .postProcess(new WebSecurityConfigurerAdapter() {
  12.                                         });
  13.                         this.webSecurity.apply(adapter);
  14.                 }
  15.                 for (SecurityFilterChain securityFilterChain : this.securityFilterChains) {
  16.                         this.webSecurity.addSecurityFilterChainBuilder(() -> securityFilterChain);
  17.                         for (Filter filter : securityFilterChain.getFilters()) {
  18.                                 if (filter instanceof FilterSecurityInterceptor) {
  19.                                         this.webSecurity.securityInterceptor((FilterSecurityInterceptor) filter);
  20.                                         break;
  21.                                 }
  22.                         }
  23.                 }
  24.                 for (WebSecurityCustomizer customizer : this.webSecurityCustomizers) {
  25.                         customizer.customize(this.webSecurity);
  26.                 }
  27.                 return this.webSecurity.build();
  28.         }
  29. }
复制代码
2)、紧张作用


  • 两种方式注册过滤器链:

    • 继承WebSecurityConfigurerAdapter(本质是实现SecurityConfigurer接口) (已弃用)
    • 直接向Spring容器中注册SecurityFilterChain对象

  • 没有默认的过滤器链时,使用WebSecurityConfigurerAdapter中默认配置生成过滤器链
  • 根据配置的SecurityFilterChain集合构建FilterChainProxy范例的对象并注入到Spring容器中名称为springSecurityFilterChain
6、HttpSecurityConfiguration

1)、部分源码
  1. @Configuration(proxyBeanMethods = false)
  2. class HttpSecurityConfiguration {
  3.         @Bean(HTTPSECURITY_BEAN_NAME)
  4.         @Scope("prototype")
  5.         HttpSecurity httpSecurity() throws Exception {
  6.                 WebSecurityConfigurerAdapter.LazyPasswordEncoder passwordEncoder = new WebSecurityConfigurerAdapter.LazyPasswordEncoder(
  7.                                 this.context);
  8.                 AuthenticationManagerBuilder authenticationBuilder = new WebSecurityConfigurerAdapter.DefaultPasswordEncoderAuthenticationManagerBuilder(
  9.                                 this.objectPostProcessor, passwordEncoder);
  10.                 authenticationBuilder.parentAuthenticationManager(authenticationManager());
  11.                 authenticationBuilder.authenticationEventPublisher(getAuthenticationEventPublisher());
  12.                 HttpSecurity http = new HttpSecurity(this.objectPostProcessor, authenticationBuilder, createSharedObjects());
  13.                 // @formatter:off
  14.                 http
  15.                         .csrf(withDefaults())
  16.                         .addFilter(new WebAsyncManagerIntegrationFilter())
  17.                         .exceptionHandling(withDefaults())
  18.                         .headers(withDefaults())
  19.                         .sessionManagement(withDefaults())
  20.                         .securityContext(withDefaults())
  21.                         .requestCache(withDefaults())
  22.                         .anonymous(withDefaults())
  23.                         .servletApi(withDefaults())
  24.                         .apply(new DefaultLoginPageConfigurer<>());
  25.                 http.logout(withDefaults());
  26.                 // @formatter:on
  27.                 applyDefaultConfigurers(http);
  28.                 return http;
  29.         }
  30. }
复制代码
2)、紧张作用


  • Spring容器中注册HttpSecurity对象
  • httpSecurity用于配置构建自界说过滤器链
六、自动装配配置类之UserDetailsServiceAutoConfiguration

1、部分源码
  1. @AutoConfiguration
  2. @ConditionalOnClass(AuthenticationManager.class)
  3. @ConditionalOnBean(ObjectPostProcessor.class)
  4. @ConditionalOnMissingBean(
  5.                 value = { AuthenticationManager.class, AuthenticationProvider.class, UserDetailsService.class,
  6.                                 AuthenticationManagerResolver.class },
  7.                 type = { "org.springframework.security.oauth2.jwt.JwtDecoder",
  8.                                 "org.springframework.security.oauth2.server.resource.introspection.OpaqueTokenIntrospector",
  9.                                 "org.springframework.security.oauth2.client.registration.ClientRegistrationRepository",
  10.                                 "org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrationRepository" })
  11. public class UserDetailsServiceAutoConfiguration {
  12.         @Bean
  13.         @Lazy
  14.         public InMemoryUserDetailsManager inMemoryUserDetailsManager(SecurityProperties properties,
  15.                         ObjectProvider<PasswordEncoder> passwordEncoder) {
  16.                 SecurityProperties.User user = properties.getUser();
  17.                 List<String> roles = user.getRoles();
  18.                 return new InMemoryUserDetailsManager(User.withUsername(user.getName())
  19.                         .password(getOrDeducePassword(user, passwordEncoder.getIfAvailable()))
  20.                         .roles(StringUtils.toStringArray(roles))
  21.                         .build());
  22.         }
  23.         private String getOrDeducePassword(SecurityProperties.User user, PasswordEncoder encoder) {
  24.                 String password = user.getPassword();
  25.                 if (user.isPasswordGenerated()) {
  26.                         logger.warn(String.format(
  27.                                         "%n%nUsing generated security password: %s%n%nThis generated password is for development use only. "
  28.                                                         + "Your security configuration must be updated before running your application in "
  29.                                                         + "production.%n",
  30.                                         user.getPassword()));
  31.                 }
  32.                 if (encoder != null || PASSWORD_ALGORITHM_PATTERN.matcher(password).matches()) {
  33.                         return password;
  34.                 }
  35.                 return NOOP_PASSWORD_PREFIX + password;
  36.         }
复制代码
2、紧张作用


  • 用户未自界说认证接口时,生成默认认证接口inMemoryUserDetailsManager(基于内存用户认证)
  • 生成默认名称为user,密码为随机生成的uuid(项目启动时会打印在控制台中),角色为空的用户存入内存中
  1. #UserDetailsServiceAutoConfiguration.inMemoryUserDetailsManager方法中获取user对象
  2. SecurityProperties.User user = properties.getUser();
  3. #SecurityProperties中的User类
  4. public static class User {
  5.                 private String name = "user";
  6.                 private String password = UUID.randomUUID().toString();
  7.                 private List<String> roles = new ArrayList<>();
  8.         }
复制代码

  • 通过配置文件可以修改默认用户名、密码、角色(示例如下)

七、自动装配配置类之SecurityFilterAutoConfiguration

1、部分源码
  1. @AutoConfiguration(after = SecurityAutoConfiguration.class)
  2. @ConditionalOnWebApplication(type = Type.SERVLET)
  3. @EnableConfigurationProperties(SecurityProperties.class)
  4. @ConditionalOnClass({ AbstractSecurityWebApplicationInitializer.class, SessionCreationPolicy.class })
  5. public class SecurityFilterAutoConfiguration {
  6.         private static final String DEFAULT_FILTER_NAME = AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME;
  7.         @Bean
  8.         @ConditionalOnBean(name = DEFAULT_FILTER_NAME)
  9.         public DelegatingFilterProxyRegistrationBean securityFilterChainRegistration(
  10.                         SecurityProperties securityProperties) {
  11.                 DelegatingFilterProxyRegistrationBean registration = new DelegatingFilterProxyRegistrationBean(
  12.                                 DEFAULT_FILTER_NAME);
  13.                 registration.setOrder(securityProperties.getFilter().getOrder());
  14.                 registration.setDispatcherTypes(getDispatcherTypes(securityProperties));
  15.                 return registration;
  16.         }
  17.         private EnumSet<DispatcherType> getDispatcherTypes(SecurityProperties securityProperties) {
  18.                 if (securityProperties.getFilter().getDispatcherTypes() == null) {
  19.                         return null;
  20.                 }
  21.                 return securityProperties.getFilter()
  22.                         .getDispatcherTypes()
  23.                         .stream()
  24.                         .map((type) -> DispatcherType.valueOf(type.name()))
  25.                         .collect(Collectors.toCollection(() -> EnumSet.noneOf(DispatcherType.class)));
  26.         }
  27. }
复制代码
2、紧张作用


  • 注册DelegatingFilterProxyRegistrationBean(委托过滤器代理注册Bean)
  • 设置代理目标Bean对象名称为springSecurityFilterChain

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

小小小幸运

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表