Spring 安全忽略 url 不适用于我们的安全忽略方法

Spring security ignore url does not work with the we security ignore method

我们正面临 SpringSecurity 忽略方法的问题。我们试图跳过一些 urls (acutator/health) 和资源的身份验证。身份验证由外部处理,我们有一个自定义过滤器来提取授权原则。

我们覆盖配置的方法如下所示:

public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/resources/**", "/actuator/health");
}
protected void configure(HttpSecurity http) throws Exception {
         http.addFilter(cutstomFilter).authorizeRequests()
        .antMatchers("/add","/update","/upload").hasAuthority("ADMIN").anyRequest().authenticated()
        .and().logout().logoutSuccessUrl("/logoutUser").and()
        .exceptionHandling().accessDeniedPage("/accessDenied").and().csrf().disable();
    }

通过给定的实现,我们的 customFilter 被调用以获取资源和运行状况 url。由于原理更改,这导致重新验证。

我们尝试添加此代码,但 customFilter 也被要求用于运行状况 url。

http.authorizeRequests().antMatchers("/actuator/health").permitAll() 

注意:检查了@Rob Winch 的回答,但不明白如果我们将那些 url 放在忽略列表中,为什么我们需要自定义文件管理器。

更新:请参阅相关@dur 的评论,它可能会在不进行重大更改的情况下解决问题。

To make it clear, your first security configuration is correct. Your problem 
is that your filter is used as a servlet filter not only as a security chain 
filter. Spring Boot does this autmatically, if you expose your filter.


OP 提到涉及执行器端点。让我们看看文档: https://spring.io/guides/topicals/spring-security-architecture

文档说:

If you want your application security rules to apply to the actuator 
endpoints, you can add a filter chain that is ordered earlier than the 
actuator one and that has a request matcher that includes all actuator 
endpoints.

文档建议将配置分成 WebSecurityConfigurerAdapter 的多个实现。

在下面的示例配置中,您应该将所谓的自定义过滤器应用于 MainAppConfigurerAdapter

“多个 Spring 引导安全配置”示例: https://medium.com/@igor.bonny/multiple-spring-boot-security-configuration-c876f1b6061e

为了跳过其他端点的身份验证,添加

.and()
.authorizeRequests().anyRequest().permitAll();

到如下所示的应用链末尾。

要验证安全设置,请为所有端​​点添加集成测试。

@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfiguration {

  @Configuration
  @Order(ManagementServerProperties.BASIC_AUTH_ORDER - 1)
  public class ActuatorConfigurerAdapter extends WebSecurityConfigurerAdapter {
    @Override
      protected void configure(HttpSecurity http) {
          http.antMatcher("/actuator/**")
          ...
      }
  }

  @Configuration
  @Order(SecurityProperties.DEFAULT_FILTER_ORDER)
  public class MainAppConfigurerAdapter extends WebSecurityConfigurerAdapter {
      @Override
      protected void configure(HttpSecurity http) {
          http.antMatcher("/api/**")
          ...
      }
  }
}

关注https://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-features.html#production-ready-endpoints-security,你应该:

  • 添加到您的属性文件

    management.endpoints.web.exposure.include=*

  • 将您的安全配置更新为

      @Configuration(proxyBeanMethods = false)
      public class ActuatorSecurity extends WebSecurityConfigurerAdapter {
    
    
      @Override
      protected void configure(HttpSecurity http) throws Exception {
          http.requestMatcher(EndpointRequest.toAnyEndpoint()).authorizeRequests((requests) ->
              requests.anyRequest().permitAll());
          }
      }
    

一种方法是在安全配置和从身份验证中提取主体的自定义过滤器中使用模式。您可以按如下方式进行:

  1. 声明忽略模式:

     static final String[] IGNORE_PATTERNS = new String[] { "**/*.js", "**/*.css", "/resources/**"};
    
  2. 声明允许所有模式:

     static final String[] PERMIT_ALL_PATTERNS = new String[] { "/login", "/logout", "/health"};
    
  3. WebSecurity:

    中使用忽略的模式
     web.ignoring().antMatchers(IGNORE_PATTERNS);
    
  4. HttpSecurity中使用允许所有模式:

     http.authorizeRequests().antMatchers(PERMIT_ALL_PATTERNS).permitAll().anyRequest().authenticated().and() ...
    
  5. 在您的过滤器中声明一个 RequestMatcher

     List<RequestMatcher> matchers = new ArrayList<>();
     for (String pattern : IGNORE_PATTERNS) {
         matchers.add(new AntPathRequestMatcher(pattern));
     }
     for (String pattern : PERMIT_ALL_PATTERNS) {
         matchers.add(new AntPathRequestMatcher(pattern));
     }
    
     RequestMatcher ignoreRequestMatcher = new OrRequestMatcher(matchers);  
    
  6. 在过滤器的doFilter方法中使用请求匹配器:

     if (ignoreRequestMatcher.matches((HttpServletRequest) request)) {
     /* skip this filter */
     chain.doFilter(request, response);
     return;  } /* rest of the filter code below */