前言
Springboot项目中,SpringSecurity作为用户认证已经成为标配。在引入SpringSecurity的项目后,我们往往会写一个WebSecurityConfig来配置用户认证规则。接下来,笔者会分三篇文章来介绍,这个认证规则是怎么应用到项目中的。
配置
下面是一个简单的WebSecurity配置,重载了三个config方法。分别配置了登录方式、用户来源和过滤特定url。
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private PasswordEncoder passwordEncoder;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.httpBasic();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("admin")
.password(passwordEncoder.encode("123456"))
.authorities("admin");
}
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/css/**", "/js/**", "/favicon.ico");
}
@Bean
public PasswordEncoder passwordEncoder() {
return PasswordEncoderFactories.createDelegatingPasswordEncoder();
}
}
源头
1. SpringBootAutoconfigure
在使用SpringBoot时,我们都可会引用或者间接引用到SpringBootAutoconfigure这个包,而这个包已经包含了一些常用的jar包的默认配置,如大家熟悉的server.port=8080。当然,SpringSecurity的默认配置也会在SpringBootAutoconfigure包内。
SpringBootAutoconfigure包会加载一系列配置类,也包括SpringSecurity的配置类,如下图。
1.1 SecurityAutoConfiguration
其中有一个SecurityAutoConfiguration类,会在项目初始化是被加载。从下面的源代码可以看到SecurityAutoConfiguration类import了WebSecurityEnablerConfiguration类
@Configuration
@ConditionalOnClass(DefaultAuthenticationEventPublisher.class)
@EnableConfigurationProperties(SecurityProperties.class)
@Import({ SpringBootWebSecurityConfiguration.class, WebSecurityEnablerConfiguration.class,
SecurityDataConfiguration.class })
public class SecurityAutoConfiguration {
...
}
1.2 WebSecurityEnablerConfiguration
WebSecurityEnablerConfiguration类加上了一个EnableWebSecurity注解
@Configuration
@EnableWebSecurity
public class WebSecurityEnablerConfiguration {
}
1.3 EnableWebSecurity
EnableWebSecurity注解又import了WebSecurityConfiguration类
...
@Import({ WebSecurityConfiguration.class,
SpringWebMvcImportSelector.class,
OAuth2ImportSelector.class })
@EnableGlobalAuthentication
@Configuration
public @interface EnableWebSecurity {
...
}
1.4 WebSecurityConfiguration
WebSecurityConfiguration类中,有两个比较重要的步骤,如下。
@Configuration
public class WebSecurityConfiguration implements ImportAware, BeanClassLoaderAware {
...
@Bean(name = AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME)
public Filter springSecurityFilterChain() throws Exception {
// 这里的webSecurityConfigurers就是我们在程序里的SpringSecurity配置
boolean hasConfigurers = webSecurityConfigurers != null
&& !webSecurityConfigurers.isEmpty();
if (!hasConfigurers) {
WebSecurityConfigurerAdapter adapter = objectObjectPostProcessor
.postProcess(new WebSecurityConfigurerAdapter() {
});
webSecurity.apply(adapter);
}
return webSecurity.build();
}
...
@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));
...
for (SecurityConfigurer<Filter, WebSecurity> webSecurityConfigurer : webSecurityConfigurers) {
webSecurity.apply(webSecurityConfigurer);
}
this.webSecurityConfigurers = webSecurityConfigurers;
}
...
}
一个是setFilterChainProxySecurityConfigurer方法,负责初始化webSecurity和webSecurityConfigurers。webSecurity可以理解为顶层的WebSecurity配置,webSecurityConfigurers是通过beanFactory找到的所有继承WebSecurityConfigurer接口的类,也包括我们自定义的WebSecurity配置。实例化后的顶层webSecurity,再应用其它的webSecurityConfigurers配置。
接下来谈谈另一个重要的方法springSecurityFilterChain的Bean注入。这个springSecurityFilterChain会调用webSecurity的build方法,会根据自定义的WebSecurity配置,来建造相应的规则。
总结
上面介绍了SpringSecurity配置的起源,了解到它是从哪里来的。下一篇会介绍,build方法是怎么建造这些规则的。
转载:https://blog.csdn.net/camel84/article/details/105255344