【问题标题】:Disable Spring Security for OPTIONS Http Method为 OPTIONS Http 方法禁用 Spring Security
【发布时间】:2014-03-08 22:17:07
【问题描述】:

是否可以为一种 HTTP 方法禁用 Spring Security?

我们有一个 Spring REST 应用程序,其服务要求将授权令牌附加到 http 请求的标头中。我正在为它编写一个 JS 客户端并使用 JQuery 发送 GET/POST 请求。该应用程序使用此过滤器代码启用了 CORS。

doFilter(....) {

  HttpServletResponse httpResp = (HttpServletResponse) response;
  httpResp.setHeader("Access-Control-Allow-Origin", "*");
  httpResp.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
  httpResp.setHeader("Access-Control-Max-Age", "3600");
  Enumeration<String> headersEnum = ((HttpServletRequest) request).getHeaders("Access-Control-Request-Headers");
  StringBuilder headers = new StringBuilder();
  String delim = "";
  while (headersEnum.hasMoreElements()) {
    headers.append(delim).append(headersEnum.nextElement());
    delim = ", ";
  }
  httpResp.setHeader("Access-Control-Allow-Headers", headers.toString());
}

但是当 JQuery 发送 CORS 的 OPTIONS 请求时,服务器会以 Authorization Failed 令牌进行响应。显然 OPTIONS 请求缺少授权令牌。那么是否可以让 OPTIONS 从 Spring 安全配置中逃脱安全层?

【问题讨论】:

    标签: java spring spring-mvc spring-security cors


    【解决方案1】:

    不推荐接受的答案,你不应该这样做。
    下面是 Spring Security 和 jQuery 的 ajax 的 CORS 设置的正确方法。

    @Configuration
    public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
       
        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
            auth.authenticationProvider(userAuthenticationProvider);
        }
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http
                .cors() // <-- This let it use "corsConfigurationSource" bean.
                    .and()
                .authorizeRequests()
                    .anyRequest().authenticated()
                    .and()
                ...
        }
    
        @Bean
        protected CorsConfigurationSource corsConfigurationSource() {
            final CorsConfiguration configuration = new CorsConfiguration();
    
            configuration.setAllowedOrigins(Collections.singletonList("http://localhost:3000"));
            configuration.setAllowedMethods(Arrays.asList("HEAD", "GET", "POST", "PUT", "DELETE", "PATCH"));
    
            // NOTE: setAllowCredentials(true) is important,
            // otherwise, the value of the 'Access-Control-Allow-Origin' header in the response
            // must not be the wildcard '*' when the request's credentials mode is 'include'.
            configuration.setAllowCredentials(true);
    
            // NOTE: setAllowedHeaders is important!
            // Without it, OPTIONS preflight request will fail with 403 Invalid CORS request
            configuration.setAllowedHeaders(Arrays.asList(
                    "Authorization",
                    "Accept",
                    "Cache-Control",
                    "Content-Type",
                    "Origin",
                    "ajax", // <-- This is needed for jQuery's ajax request.
                    "x-csrf-token",
                    "x-requested-with"
            ));
    
            final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
            source.registerCorsConfiguration("/**", configuration);
            return source;
        }
    }
    

    从 jQuery 方面。

    $.ajaxSetup({
        // NOTE: Necessary for CORS
        crossDomain: true,
        xhrFields: {
            withCredentials: true
        }
    });
    

    【讨论】:

      【解决方案2】:

      如果您使用的是基于注释的安全配置,那么您应该通过在配置中调用 .cors() 来将 spring 的 CorsFilter 添加到应用程序上下文中,如下所示:

      @Override
      protected void configure(HttpSecurity http) throws Exception
      {
           http
          .csrf().disable()
          .authorizeRequests()
            .antMatchers("/resources/**").permitAll()
            .anyRequest().authenticated()
          .and()
          .formLogin()
          .and()
          .httpBasic()
          .and()
          .cors();
      }
      

      【讨论】:

        【解决方案3】:

        在某些情况下,使用WebSecurityConfigurerAdapter解决cors问题时需要将configuration.setAllowedHeaders(Arrays.asList("Content-Type"));添加到corsConfigurationSource()

        【讨论】:

          【解决方案4】:

          如果您使用基于注解的安全配置文件 (@EnableWebSecurity & @Configuration),您可以在 configure() 方法中执行以下操作,以允许 Spring Security 允许 OPTION 请求没有给定路径的身份验证:

          @Override
          protected void configure(HttpSecurity http) throws Exception
          {
               http
              .csrf().disable()
              .authorizeRequests()
                .antMatchers(HttpMethod.OPTIONS,"/path/to/allow").permitAll()//allow CORS option calls
                .antMatchers("/resources/**").permitAll()
                .anyRequest().authenticated()
              .and()
              .formLogin()
              .and()
              .httpBasic();
          }
          

          【讨论】:

          • +1 正是我们为启用 CORS OPTIONS 请求所做的工作。
          • 它工作正常感谢您的提示我搜索和调试很多但现在无法修复我已修复它以使用此提示
          • 我在研究类似问题时找到了您的答案,该问题尚未以目前的形式响应您的解决方案。你愿意看看吗?这是链接:stackoverflow.com/questions/36705874/…
          • 我自己不是 Java Spring 用户,我在后端使用不同的语言时遇到了同样的问题。 Java/Spring 是否在安全性方面带来了任何额外的抽象,或者忽略所有 OPTIONS 请求的身份验证中间件方法是最安全的?
          【解决方案5】:

          如果有人正在寻找使用 Spring Boot 的简单解决方案。只需添加一个额外的 bean:

             @Bean
             public IgnoredRequestCustomizer optionsIgnoredRequestsCustomizer() {
                return configurer -> {
                   List<RequestMatcher> matchers = new ArrayList<>();
                   matchers.add(new AntPathRequestMatcher("/**", "OPTIONS"));
                   configurer.requestMatchers(new OrRequestMatcher(matchers));
                };
             }
          

          请注意,根据您的应用程序,这可能会为潜在的攻击打开它。

          打开问题以获得更好的解决方案:https://github.com/spring-projects/spring-security/issues/4448

          【讨论】:

          • IgnoredRequestCustomizer 自 Spring Boot 2 以来已弃用。
          【解决方案6】:

          允许上下文中的所有选项:

              @Override
              public void configure(WebSecurity web) throws Exception {
                  web.ignoring().antMatchers(HttpMethod.OPTIONS, "/**");
              }
          

          【讨论】:

          • 这似乎是允许 OPTIONS 请求而不需要授权的唯一方法。
          • 如果您随后创建了一个您想要保护的选项端点,您将忘记配置中的排除项,每个人都可以访问它。您应该考虑使用过滤器来允许从 spring-security 中排除 cors 选项请求:docs.spring.io/spring-security/site/docs/4.2.x/reference/html/…
          • 带 HttpSecurity 的是 http.authorizeRequests() .antMatchers(HttpMethod.OPTIONS, "/registrybrain/**").permitAll()
          • 花了 2 多个小时尝试并找到解决方案 - 只有这个有效。
          • “如果你创建一个你想要保护的选项端点”@Tim 为什么会有人需要它?
          【解决方案7】:

          你试过了吗

          您可以使用多个元素来定义不同的 不同 URL 集的访问要求,但它们将是 按列出的顺序进行评估,并将使用第一个匹配项。那么你 必须将最具体的匹配项放在顶部。您还可以添加一个 方法属性将匹配限制为特定的 HTTP 方法(GET、 POST、PUT 等)。

          <http auto-config="true">
              <intercept-url pattern="/client/edit" access="isAuthenticated" method="GET" />
              <intercept-url pattern="/client/edit" access="hasRole('EDITOR')" method="POST" />
          </http>
          

          上面的意思是你需要选择要拦截的url模式和你想要什么方法

          【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2017-07-11
          • 2017-10-24
          • 2016-05-10
          • 2018-08-26
          • 2018-03-07
          • 1970-01-01
          • 1970-01-01
          • 2015-04-23
          相关资源
          最近更新 更多