小秦哥 发表于 2022-9-16 17:15:37

Spring Security定义多个过滤器链(10)

  在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注解来标记不同配置的优先级(即不同过滤器链的优先级),数字越大优先级越低,当请求到来时,会按照过滤器链的优先级从高往低,依次进行匹配。
  
  
 

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
页: [1]
查看完整版本: Spring Security定义多个过滤器链(10)