在Spring Security中可以同時存在多個過濾器鏈,一個WebSecurityConfigurerAdapter的實例就可以配置一條過濾器鏈。 我們來看如下一個案例: @Configuration public class SecurityConfig { @Bean UserDetails ...
在Spring Security中可以同時存在多個過濾器鏈,一個WebSecurityConfigurerAdapter的實例就可以配置一條過濾器鏈。
我們來看如下一個案例:
@Configuration
public class SecurityConfig {
@Bean
UserDetailsService us(){
InMemoryUserDetailsManager users = new InMemoryUserDetailsManager();
users.createUser(User.withUsername("劍氣近").password("{noop}123").roles("admin").build());
return users;
}
@Configuration
@Order(1)
static class SecurityConfig01 extends WebSecurityConfigurerAdapter{
@Override
protected void configure(HttpSecurity http) throws Exception {
InMemoryUserDetailsManager users = new InMemoryUserDetailsManager();
users.createUser(User.withUsername("chain1in").password("{noop}123").roles("admin").build());
http.antMatcher("/bar/**")
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/mylogin.html")
.loginProcessingUrl("/bar/login")
.successHandler(((req, resp, auth) -> {
resp.setContentType("application/json;charset=UTF-8");
String s = new ObjectMapper().writeValueAsString(auth);
resp.getWriter().write(s);
}))
.permitAll()
.and()
.csrf().disable()
.userDetailsService(users);
}
}
@Configuration
@Order(2)
static class SecurityConfig02 extends WebSecurityConfigurerAdapter{
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("chain2out").password("{noop}123").roles("admin");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
InMemoryUserDetailsManager users = new InMemoryUserDetailsManager();
users.createUser(User.withUsername("chain2in").password("{noop}123").roles("admin").build());
http.antMatcher("/foo/**")
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/mylogin.html")
.loginProcessingUrl("/foo/login")
.successHandler(((req, resp, auth) -> {
resp.setContentType("application/json;charset=UTF-8");
String s = new ObjectMapper().writeValueAsString(auth);
resp.getWriter().write(s);
}))
.permitAll()
.and()
.csrf().disable()
.userDetailsService(users);
}
}
}
在SecurityConfig中分別定義兩個靜態內部類SecurityConfig01和SecurityConfig02,兩個配置類都繼承自WebSecurityConfigurerAdapter, 可以分別配置一條過濾器鏈。
先來看Security01,在Security01中,我們設置過濾器鏈的攔截規則是/bar/**,即如果請求路徑是/bar/**格式的,則進入到Security01的過濾器鏈中進行處理。同時我們配置了局部 AuthenticationManager 對應的用戶是 chain1in/123 ,由於沒有重寫 configure(AuthenticationManagerBuilder)方法,所以註冊到 Spring 容器中的 UserDetailsService 將作為局部 AuthenticationManager的parent對應的用戶,換句話說,如果登錄的路徑是/bar/login,那麼升發者可以使用 chain1in/123和 劍氣近/123兩個用戶進行登錄。
再來看SecurityConfig02。在Security02中,我們設置過濾器鏈的攔截規則是/foo/**,即如果請求路徑是/foo/**格式的,則進入到Secunty02的過濾器鏈中進行處理,同時我們配置了局部 AuthenticationManager 對應的用戶是 chain2in/123 ,由於重寫了 configure(Authentication ManagerBuilder)方法,在該方法中定義了局部AuthenticationManager的parent對應的用戶,此時註冊到Spring容器中的UserDetailsService實例對於/foo/**過濾器鏈不再生效。換句話說, 如果登錄路徑是/foo/login,開發者可以使用chain2in/123和 chain2out/123兩個用戶進行登錄,而不可以使用 劍氣近/123進行登錄。
需要註意的是,如果配置了多個過濾器鏈,需要使用@Order註解來標記不同配置的優先順序(即不同過濾器鏈的優先順序),數字越大優先順序越低,當請求到來時,會按照過濾器鏈的優先順序從高往低,依次進行匹配。