在Spring Security中可以定義多個過濾器鏈,一個WebSerityConfigurerAdapter的實例就可以配置一個過濾器鏈,我們只需要配置多個WebSerityConfigurerAdapter的實例即可
可以看到,當請求到達 FilterChainProxy 之后,FilterChainProxy 會根據請求的路徑,將請求轉發到不同的 過濾器鏈 上面去,不同的 過濾器鏈 對應了不同的過濾器,也就是不同的請求將經過不同的過濾器。
@Configuration
public class SecurityConfig {
@Bean
protected UserDetailsService userDetailsService() {
InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
manager.createUser(User.withUsername("javaboy").password("{bcrypt}$2a$10$Sb1gAUH4wwazfNiqflKZve4Ubh.spJcxgHG8Cp29DeGya5zsHENqi").roles("admin", "aaa", "bbb").build());
manager.createUser(User.withUsername("sang").password("{noop}123").roles("admin").build());
manager.createUser(User.withUsername("江南一點雨").password("{MD5}{Wucj/L8wMTMzFi3oBKWsETNeXbMFaHZW9vCK9mahMHc=}4d43db282b36d7f0421498fdc693f2a2").roles("user", "aaa", "bbb").build());
return manager;
}
@Configuration
@Order(1)
static class DefaultWebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.antMatcher("/foo/**")
.authorizeRequests()
.anyRequest().hasRole("admin")
.and()
.csrf().disable();
}
}
@Configuration
@Order(2)
static class DefaultWebSecurityConfig2 extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.antMatcher("/bar/**")
.authorizeRequests()
.anyRequest().hasRole("user")
.and()
.formLogin()
.permitAll()
.and()
.csrf().disable();
}
}
}
(1)首先,SecurityConfig 不再需要繼承自 WebSecurityConfigurerAdapter 了,只是作為一個普通的配置類,加上 @Configuration 注解即可。
(2)提供 UserDetailsService 實例,相當於是我們的數據源。
(3)創建靜態內部類繼承 WebSecurityConfigurerAdapter 類,同時用 @Configuration 注解標記靜態內部類是一個配置類,配置類里邊的代碼就和之前的一樣了,無需贅述。
(4)每一個靜態內部類相當於就是一個過濾器鏈的配置。
(5)注意在靜態內部類里邊,我沒有使用 http.authorizeRequests() 開始,http.authorizeRequests() 配置表示該過濾器鏈過濾的路徑是 /**。在靜態內部類里邊,我是用了 http.antMatcher("/bar/**") 開啟配置,表示將當前過濾器鏈的攔截范圍限定在 /bar/**。所以有的時候authorizeRequests()不能放在第一個位置
(6)當存在多個過濾器鏈的時候,必然會有一個優先級的問題,所以每一個過濾器鏈的配置類上通過 @Order(2) 注解來標記優先級。數字越大優先級越低。請求會先進入優先級高的過濾器鏈中。