【问题标题】:Spring Security multiple url ruleset not working togetherSpring Security 多个 url 规则集不能一起工作
【发布时间】:2017-01-20 07:02:05
【问题描述】:

我有一个 HTTP Spring Security 配置,当我注释掉每个单独的方面时它似乎工作,但当我将 Spring Security 规则组合在一起时它不起作用,所以我知道问题不在于 regexMatcherantMatcher 但要结合应用规则。

这是我的 Spring Security 课程:

package com.driver.website.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.csrf.CsrfTokenRepository;
import org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository;
import org.springframework.security.web.header.writers.StaticHeadersWriter;
import org.springframework.security.web.header.writers.frameoptions.XFrameOptionsHeaderWriter;
import org.springframework.security.web.util.matcher.RequestMatcher;

import javax.servlet.http.HttpServletRequest;
import java.security.AccessControlContext;

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Value("${widget.headers.xframeoptions.domains.allowed}")
    private String allowedXFrameOptions;

    @Value("${widget.headers.origins.allowed}")
    private String allowedOrigins;

    @Override
    public void configure(HttpSecurity http) throws Exception {
        // @formatter:off

        http.exceptionHandling().accessDeniedPage("/login")
                .and()
                .formLogin().loginPage("/login").defaultSuccessUrl("/myaccount", true).permitAll()
                .and()
                .authorizeRequests()
                .antMatchers("/**").permitAll();

        http.regexMatcher("^((?!(/widget|/assistedSearch)).)*$")
                .headers().frameOptions().disable()
                .regexMatcher("^((?!(/widget|/assistedSearch)).)*$")
                .headers()
                .xssProtection()
                .contentTypeOptions()
                .addHeaderWriter(new StaticHeadersWriter("X-FRAME-OPTIONS", "SAMEORIGIN"));

        http.antMatcher("/widget")
            .headers()
            .frameOptions()
            .disable()
            .antMatcher("/widget")
            .headers()
            .addHeaderWriter(new StaticHeadersWriter("X-FRAME-OPTIONS", "ALLOW-FROM " + allowedXFrameOptions));

        http.requestMatchers().antMatchers("/assistedSearch", "/widget")
            .and()
            .headers()
            .addHeaderWriter(new StaticHeadersWriter("Access-Control-Allow-Origin", allowedOrigins))
            .addHeaderWriter(new StaticHeadersWriter("Access-Control-Allow-Methods", "GET, POST"))
            .addHeaderWriter(new StaticHeadersWriter("Access-Control-Allow-Headers", "Content-Type"));

        // @formatter:on
    }
}

规则应该是……

  • 对于除 /widget 和 /assistedSearch 之外的所有 url,我们应该添加 SAMEORIGIN X-Frame-Options 标头
  • 对于/widget 端点,我们应该添加 X-Frame-Options: ALLOW-FROM 标头
  • 对于/widget/assistedSearch 端点,我们应该添加Access-Control-Allow-OriginAccess-Control-Allow-MethodsAccess-Control-Allow-Headers 标头

正如我上面提到的,如果我注释掉 For all urls 规则集,那么其他两个会同时工作,但如果 For all urls 规则未注释,则不会出现任何标题。

有人知道为什么会这样吗?如何在 Spring Security 中添加多个规则集并用新规则集覆盖现有规则集?​​

我试过了

http.antMatcher("/widget")
    .headers()
    .frameOptions()
    .disable()

这似乎又可以单独使用,但不能组合使用。

提前致谢!

【问题讨论】:

  • 只能添加不能覆盖规则。此外,只会应用第一个匹配项,因此具有相同模式(或可能的匹配模式)的多个规则将不起作用,因为只有第一个匹配项会获胜。这些规则也按照它们定义的顺序进行处理。由于首先定义了您的/**,因此您的所有其他规则几乎都没用。在参考指南中很明显(如果我没记错的话,是粗体字)/** 应该始终是链中的最后一个。
  • @M.Deinum 我已将 everything but not /widget and /assistedSearch 规则集作为最后一个声明移动,这意味着该规则已正确应用,但 /widget 和 /assistedSearch 规则未正确应用。现在我知道您已经说过它们是附加的,但从技术上讲,我只向 /widget 和 /assistedSearch 添加了一个规则集,那么为什么这意味着没有任何标题显示?
  • 所以这个问题被降级是非常荒谬的。这是一个有效的。我在这里指定互斥规则集。如果不能使用互斥规则集,为什么还要提供正则表达式的力量?有谁知道解决这个问题的最佳实践。我是否必须指定拦截器而不是使用 DSL 处理它?
  • 你不能必须antMatchers("/widget"),因为这样只有 1 将适用,而不是两者都适用。我的意思是说每个匹配器模式都被添加一次。对于/widget,您有 3 个匹配器,但只有一个,可能会应用第一个,而不是全部。
  • 感谢您的帮助。所以基本上我需要一个包含所有“/widget”规则的静态类和一个单独的“/assistedSearch”规则集。当然,这意味着两者都有重复的规则,但至少有关注点分离,更重要的是它会起作用。我会调查一下并发布我的解决方案。

标签: java spring spring-security


【解决方案1】:

您覆盖了以前的匹配器,请参阅HttpSecurity.html#antMatcher

调用antMatcher(String) 将覆盖之前对mvcMatcher(String)}requestMatchers()antMatcher(String)regexMatcher(String)requestMatcher(RequestMatcher) 的调用。

HttpSecurity.html#regexMatcher:

调用regexMatcher(String) 将覆盖之前对mvcMatcher(String)}requestMatchers()antMatcher(String)regexMatcher(String)requestMatcher(RequestMatcher) 的调用。

如果您想要HttpSecurity 的多个配置,请参阅Spring Security Reference

我们可以配置多个 HttpSecurity 实例,就像我们可以拥有多个 <http> 块一样。关键是多次扩展WebSecurityConfigurationAdapter。例如,以下是对以 /api/ 开头的 URL 进行不同配置的示例。

@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();
      }
  }
}

【讨论】:

  • 感谢您的回答。我为每个规则实现了静态类,然后为每个规则使用正确的@Order 应用它们。一旦您了解了 Spring Security 在幕后的工作原理,那么这一切都是有意义的。
猜你喜欢
  • 2012-04-24
  • 1970-01-01
  • 2011-12-15
  • 1970-01-01
  • 2018-06-02
  • 1970-01-01
  • 2023-04-08
  • 2016-04-18
  • 1970-01-01
相关资源
最近更新 更多