在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(httpsSecurity https) throws Exception { InMemoryUserDetailsManager users = new InMemoryUserDetailsManager(); users.createUser(User.withUsername("chain1in").password("{noop}123").roles("admin").build()); https.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(httpsSecurity https) throws Exception { InMemoryUserDetailsManager users = new InMemoryUserDetailsManager(); users.createUser(User.withUsername("chain2in").password("{noop}123").roles("admin").build()); https.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注解来标记不同配置的优先级(即不同过滤器链的优先级),数字越大优先级越低,当请求到来时,会按照过滤器链的优先级从高往低,依次进行匹配。