Spring - CORS 不适用于安全配置

Posted

技术标签:

【中文标题】Spring - CORS 不适用于安全配置【英文标题】:Spring - CORS not working with Security Config 【发布时间】:2019-05-25 09:50:18 【问题描述】:

我开发了一个带有 spring webflux 后端的 Angular 应用程序。到目前为止,CorsFilter 工作正常并允许来自前端的请求。

然后我添加了一个 SecurityConfig。从那时起,CorsFilter 停止工作,我在 Angular 应用程序中遇到异常:

从源“http://localhost:4200”访问“http://localhost:8080/users/999/folders/%2F/media/”处的 XMLHttpRequest 已被 CORS 策略阻止:对预检请求的响应未通过访问控制检查:没有“Access-Control-Allow-Origin”标头出现在请求的资源上

这个过滤器效果很好:

@Configuration
public class CorsFilter 

    private static final String FRONTEND_LOCALHOST = "http://localhost:4200";
    private static final String FRONTEND_STAGING = "https://somehost.github.io";

    @Bean
    CorsWebFilter corsWebFilter() 
        CorsConfiguration corsConfig = new CorsConfiguration();
        corsConfig.applyPermitDefaultValues();
        corsConfig.addAllowedMethod(HttpMethod.PUT);
        corsConfig.addAllowedMethod(HttpMethod.DELETE);
        corsConfig.setAllowedOrigins(Arrays.asList(FRONTEND_LOCALHOST, FRONTEND_STAGING));

        UrlBasedCorsConfigurationSource source =
                new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", corsConfig);

        return new CorsWebFilter(source);
    

然后我使用以下 SecurityConfig 添加了授权(不记名令牌):

@EnableWebFluxSecurity
@EnableReactiveMethodSecurity
public class SecurityConfiguration 

    @Bean
    public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) 
        http.cors().and().csrf()
            .csrfTokenRepository(CookieServerCsrfTokenRepository.withHttpOnlyFalse())
            .and()
            .authorizeExchange()
            .anyExchange().authenticated()
            .and()
            .oauth2ResourceServer()
            .jwt();
        return http.build();
    

似乎不再考虑我的 CorsFilter 安全配置。我认为需要在配置中明确添加 corsfilter,但我发现的示例不起作用。我希望有人可以提供帮助并知道原因。

编辑:为了解决重复问题:我已经尝试将 cors()cors().configurationSource(corsConfig()) 添加到我的安全配置中,但也没有帮助。

【问题讨论】:

感谢您一直以来的帮助:),我已经完成了。我现在找到了解决方案。将作为答案发布。 CORS issue - No 'Access-Control-Allow-Origin' header is present on the requested resource的可能重复 这是一个老问题,但它是唯一对我有用的答案。它也不是重复的@jww,因为您的链接中的配置是针对非反应性 java 而这个问题和答案是关于反应性 java。 【参考方案1】:

我通过实现自定义 corsfilter 在Enable CORS in Spring 5 Webflux? 中找到了一种工作方式。

但是我仍然对该解决方案不满意,因为它看起来很像一种解决方法。

我终于找到了罪魁祸首……一个很尴尬。我发布的 SecurityConfig 位于错误的包中(它意外地位于默认包中),因此配置没有被拾取。

当我将代码粘贴到 securityconfig 时,问题中的 cors 过滤器也开始工作。

所以我最终的 SecurityConfig 如下所示:

import java.util.Arrays;

import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.method.configuration.EnableReactiveMethodSecurity;
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.web.server.SecurityWebFilterChain;
import org.springframework.security.web.server.csrf.CookieServerCsrfTokenRepository;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.reactive.CorsConfigurationSource;
import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;

@EnableWebFluxSecurity
@EnableReactiveMethodSecurity
public class SecurityConfiguration 

    private static final String FRONTEND_LOCALHOST = "http://localhost:4200";
    private static final String FRONTEND_STAGING = "https://somehost.github.io";

    @Bean
    public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) 
        http
                .csrf()
                .csrfTokenRepository(CookieServerCsrfTokenRepository.withHttpOnlyFalse())
                .and()
                .authorizeExchange()
                .anyExchange().authenticated()
                .and()
                .oauth2ResourceServer()
                .jwt();
        return http.build();
    


    @Bean
    CorsConfigurationSource corsConfiguration() 
        CorsConfiguration corsConfig = new CorsConfiguration();
        corsConfig.applyPermitDefaultValues();
        corsConfig.addAllowedMethod(HttpMethod.PUT);
        corsConfig.addAllowedMethod(HttpMethod.DELETE);
        corsConfig.setAllowedOrigins(Arrays.asList(FRONTEND_LOCALHOST, FRONTEND_STAGING));

        UrlBasedCorsConfigurationSource source =
                new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", corsConfig);
        return source;
    

【讨论】:

【参考方案2】:

尝试添加此配置

corsConfig.setAllowCredentials(true);

【讨论】:

感谢您的提示,但我使用不记名令牌,所以我不发送任何凭据。所以这不是问题

以上是关于Spring - CORS 不适用于安全配置的主要内容,如果未能解决你的问题,请参考以下文章

Spring 安全忽略 url 不适用于我们的安全忽略方法 [重复]

cors 不适用于我的 Spring Boot 应用程序

Spring Security 保护路由 hasRole,hasAuthority 不适用于 CORS http 请求

发布请求不适用于 Spring 安全性和 Angular 5

Thymeleaf 安全不适用于 Spring Boot 1.3.5

Spring Boot - CORS 过滤器适用于 GET,但不适用于其他 HTTP 动词