在使用SpringSecurity时,我们默认的配置是来自 org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration (用于完成过滤器链的配置)和 org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration(用于认证)。
1. 其中 SecurityAutoConfiguration导入了SpringBootWebSecurityConfiguration 类来完成默认配置(具体见上文)。我们可以通过添加自定义的 org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter子类来覆盖默认的过滤器链的配置。springboot只要类路径下能找到 WebSecurityConfigurer 接口的实现类后,就不会加载相应的默认配置。如下所示( 通过配置禁止了跨域请求):
@EnableWebSecurity public class MyWebSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.csrf().disable();// 关闭csrf
super.configure(http) ; } }
2. UserDetailsServiceAutoConfiguration类只配置了一个bean,UserDetailsService接口的内存实现,用于认证
@Configuration @ConditionalOnClass(AuthenticationManager.class) @ConditionalOnBean(ObjectPostProcessor.class) @ConditionalOnMissingBean({ AuthenticationManager.class, AuthenticationProvider.class, UserDetailsService.class }) public class UserDetailsServiceAutoConfiguration { private static final String NOOP_PASSWORD_PREFIX = "{noop}"; private static final Pattern PASSWORD_ALGORITHM_PATTERN = Pattern .compile("^\\{.+}.*$"); private static final Log logger = LogFactory .getLog(UserDetailsServiceAutoConfiguration.class); @Bean @ConditionalOnMissingBean(type = "org.springframework.security.oauth2.client.registration.ClientRegistrationRepository") @Lazy public InMemoryUserDetailsManager inMemoryUserDetailsManager( SecurityProperties properties, ObjectProvider<PasswordEncoder> passwordEncoder) { SecurityProperties.User user = properties.getUser(); List<String> roles = user.getRoles(); return new InMemoryUserDetailsManager(User.withUsername(user.getName()) .password(getOrDeducePassword(user, passwordEncoder.getIfAvailable())) .roles(StringUtils.toStringArray(roles)).build()); } private String getOrDeducePassword(SecurityProperties.User user, PasswordEncoder encoder) { String password = user.getPassword(); if (user.isPasswordGenerated()) { logger.info(String.format("%n%nUsing generated security password: %s%n", user.getPassword())); } if (encoder != null || PASSWORD_ALGORITHM_PATTERN.matcher(password).matches()) { return password; } return NOOP_PASSWORD_PREFIX + password; } }
UserDetailsService接口源码:
public interface UserDetailsService { UserDetails loadUserByUsername(String username) throws UsernameNotFoundException; // 用于通过用户名获取用户信息 }