Spring Security:多个 HTTP 配置不起作用

Posted

技术标签:

【中文标题】Spring Security:多个 HTTP 配置不起作用【英文标题】:Spring Security : Multiple HTTP Config not working 【发布时间】:2019-06-13 14:27:43 【问题描述】:

我正在尝试使用 Spring Security,并且我有一个用例,我希望保护不同的登录页面和不同的 URL 集。

这是我的配置:

@Configuration
@Order(1)
public static class ProviderSecurity extends WebSecurityConfigurerAdapter
    @Override
    protected void configure(HttpSecurity http) throws Exception 
        http
            .authorizeRequests()
                .antMatchers("/", "/home").permitAll()
                .antMatchers("/admin/login").permitAll()
                .antMatchers("/admin/**").access("hasRole('BASE_USER')")
                .and()
            .formLogin()
                .loginPage("/admin/login").permitAll()
                .defaultSuccessUrl("/admin/home")
                .failureUrl("/admin/login?error=true").permitAll()
                .usernameParameter("username")
                .passwordParameter("password")
                .and()
            .csrf()                    
                .and()
            .exceptionHandling().accessDeniedPage("/Access_Denied");            
    



@Configuration
@Order(2)
public static class ConsumerSecurity extends WebSecurityConfigurerAdapter 

    @Override
    protected void configure(HttpSecurity http) throws Exception 
        http
            .authorizeRequests()
                .antMatchers("/consumer/login").permitAll()
                .antMatchers("/consumer/**").access("hasRole('BASE_USER')")
                .anyRequest().authenticated()
                .and()
            .formLogin()
                .loginPage("/consumer/login").permitAll()
                .defaultSuccessUrl("/consumer/home")
                .failureUrl("/consumer/login?error=true").permitAll()
                .usernameParameter("username")
                .passwordParameter("password")
                .and().csrf()                
                .and()
            .exceptionHandling().accessDeniedPage("/Access_Denied");
    

这些类是另一个类MultipleHttpSecurityConfig 的内部类,该类具有注释@EnableWebSecurity

admin/** 的安全性工作正常,但没有一个consumer/** 页面是安全的,登录页面没有发生重定向。我已经搜索了其他答案,但没有一个有效。

【问题讨论】:

【参考方案1】:

看Spring Security Reference:

@EnableWebSecurity
public class MultiHttpSecurityConfig 
  @Autowired
  public void configureGlobal(AuthenticationManagerBuilder auth)  1
      auth
          .inMemoryAuthentication()
              .withUser("user").password("password").roles("USER").and()
              .withUser("admin").password("password").roles("USER", "ADMIN");
  

  @Configuration
  @Order(1)                                                        2
  public static class ApiWebSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter 
      protected void configure(HttpSecurity http) throws Exception 
          http
              .antMatcher("/api/**")                               3
              .authorizeRequests()
                  .anyRequest().hasRole("ADMIN")
                  .and()
              .httpBasic();
      
      

  @Configuration                                                   4
  public static class FormLoginWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter 

      @Override
      protected void configure(HttpSecurity http) throws Exception 
          http
              .authorizeRequests()
                  .anyRequest().authenticated()
                  .and()
              .formLogin();
      
  

1 正常配置身份验证

2 创建一个包含@OrderWebSecurityConfigurerAdapter 实例,以指定应首先考虑哪个WebSecurityConfigurerAdapter

3 http.antMatcher 声明此 HttpSecurity 仅适用于以 /api/ 开头的 URL

4 创建WebSecurityConfigurerAdapter 的另一个实例。如果 URL 不以 /api/ 开头,则将使用此配置。此配置在ApiWebSecurityConfigurationAdapter 之后考虑,因为它在1 之后有一个@Order 值(没有@Order 默认为最后一个)。

没有使用您的第二个配置,因为您的第一个配置匹配 /**(未配置 antMatcher)。而且您的第一个配置仅限制/admin/**,默认情况下允许所有其他URL。

【讨论】:

换句话说,您可以指定多个WebSecurityConfigurerAdapters,它们按照@Order注释中指定的优先级顺序考虑。 第一个匹配的 .requestMatchers().antMatchers("/matcher/**") 被使用,其他的被丢弃。即,WebSecurityConfigurerAdapters 不堆叠。【参考方案2】:

你的第一个WebSecurityConfigurerAdapter

http
            .authorizeRequests()

匹配所有 URL,通过使用 antMatcher 将其限制为仅以 /admin 开头的 URL:

@Configuration
@Order(1)
public static class ProviderSecurity extends WebSecurityConfigurerAdapter
    @Override
    protected void configure(HttpSecurity http) throws Exception 
        http
            .antMatcher("/admin/**")
                .authorizeRequests()
                .antMatchers("/admin/login").permitAll()
                .antMatchers("/admin/**").access("hasRole('BASE_USER')")
                .and()

                ...

【讨论】:

以上是关于Spring Security:多个 HTTP 配置不起作用的主要内容,如果未能解决你的问题,请参考以下文章

Spring Security:如何在使用多个“http”元素时为给定 URL 授权用户?

Spring security invalid-session-url 的坑(配了permitAll仍然跳转到登录页)

Spring security - 指定顺序时多个httpsecurity不起作用[重复]

Spring Security 可以支持多个入口点吗?

spring mvc集成spring security 案例

使用 CAS + Spring Security 实现 SSO