ChatGPT解决这个技术问题 Extra ChatGPT

为 OPTIONS Http 方法禁用 Spring Security

是否可以为一种 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 安全配置中逃脱安全层?


D
Daniel Gray

如果您使用基于注释的安全配置文件 (@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 请求的身份验证中间件方法是最安全的?
L
Luc S.

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

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

这似乎是允许 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 为什么会有人需要它?
K
Koitoer

你试过这个

您可以使用多个元素为不同的 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模式和你想要的方法


但我想我们不能有像 <intercept-url pattern="/client/edit" access="hasRole('EDITOR')" method="POST, OPTIONS" /> 这样的东西。正确的 ?
如果使用 @PreAuthorize 注释,这将如何工作,我希望 Put 方法具有管理员访问权限,而 Post 方法具有用户访问权限
java config中的等价物是什么
请看看我的问题。 stackoverflow.com/questions/50579277/…
D
Dennis Kieselhorst

如果有人正在寻找使用 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 起已弃用。
w
wonsuc

不推荐接受的答案,你不应该这样做。下面是 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
    }
});

M
Meysam

如果您使用的是基于注释的安全配置,那么您应该通过在配置中调用 .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();
}

F
FabianoLothor

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