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。