SpringSecurity的配置分析

在使用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; // 用于通过用户名获取用户信息
}

猜你喜欢

转载自www.cnblogs.com/hzhuxin/p/10758834.html