为什么我在发送正确的标头时会收到 Spring Boot (Java) 错误 Access-Control-Allow-Origin can't be *?

问题描述 投票:0回答:2

我有一个简单的 Web 应用程序,其中包含 Angular 前端和使用 Spring security JWT 身份验证(版本 3.0.5)的 Spring Boot API,部署在 Tomcat 10 中。Web 服务器和 APP/DB 服务器是分开的。出于隐私原因,我将审查该域名,并将其替换为 example.com。

我的 Cors 配置如下:

CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(Collections.singletonList("http://goods.example.com"));
        configuration.setAllowedMethods(Arrays.asList("GET","POST", "PUT", "OPTIONS"));
        configuration.setAllowCredentials(true);
        configuration.setAllowedHeaders(Arrays.asList("Origin", "Access-Control-Allow-Origin", "Content-Type",
                "Accept", "Jwt-Token", "Authorization", "X-Requested-With",
                "Access-Control-Request-Method", "Access-Control-Request-Headers"));
        configuration.setExposedHeaders(Arrays.asList("Origin", "Content-Type", "Accept", "Jwt-Token", "Authorization",
                "Access-Control-Allow-Origin", "Access-Control-Allow-Origin", "Access-Control-Allow-Credentials", "Filename"));
        configuration.setMaxAge(3600L);
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }

我的 Spring Security 配置如下:

@Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {
        httpSecurity
                .cors()
                .configurationSource(corsConfigurationSource())
                .and()
                .csrf()
                .disable()
//                .requiresChannel()
//                .anyRequest()
//                .requiresSecure()
//                .and()
                .authorizeHttpRequests( authCustomizer -> authCustomizer
                        .requestMatchers(HttpMethod.POST, "/api/v1/auth/authenticate").permitAll()
                        .requestMatchers(HttpMethod.GET, "/api/v1/test").permitAll()
                )
                .authorizeHttpRequests()
                .anyRequest()
                .authenticated()
                .and()
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .authenticationProvider(authenticationProvider)
                .addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class)
                .headers()
                .xssProtection()
                .and()
                .contentSecurityPolicy("default-src 'self' data: blob:;");

        return httpSecurity.build();
    }

如您所见,我现在正在 http 上运行该应用程序。

当我使用有效凭据调用身份验证端点时,它会显示以下标头:

HTTP/1.1 403 
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Access-Control-Allow-Origin: http://goods.example.com
Access-Control-Expose-Headers: Origin, Content-Type, Accept, Jwt-Token, Authorization, Access-Control-Allow-Origin, Access-Control-Allow-Origin, Access-Control-Allow-Credentials, Filename
Access-Control-Allow-Credentials: true
X-Content-Type-Options: nosniff
X-XSS-Protection: 0
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Frame-Options: DENY
Content-Type: application/json
Transfer-Encoding: chunked
Date: Wed, 03 May 2023 09:11:19 GMT
Keep-Alive: timeout=20
Connection: keep-alive

现在问题来了。在我的日志中,我收到以下错误:

c.o.g.exception.DefaultExceptionHandler  : java.lang.IllegalArgumentException: When allowCredentials is true, allowedOrigins cannot contain the special value "*" since that cannot be set on the "Access-Control-Allow-Origin" response header. To allow credentials to a set of origins, list them explicitly or consider using "allowedOriginPatterns" instead.

在我看来,我在我的 cors 配置中明确列出了允许的来源,但由于某种原因它不起作用......

我尝试过的:

  • 我尝试将 Collections.singletonList() 更改为 Arrays.asList()
  • 删除 XSS 和 CSP
  • 将类注释顺序更改为:
    @Order(Ordered.HIGHEST_PRECEDENCE)
  • 检查Tomcat中是否有激活的cors规则(我找不到)
  • 使用 setAllowedOriginPatterns 或 addAllowedOriginPattern 而不是 setAllowOrigins
  • 将@Bean注释添加到我的CorsConfigurationSource

这些是我在其他线程中找到的修复/我自己可以想到的修复。

需要说明的是,我在浏览器中没有收到错误,只是在 Java/Tomcat 中收到错误。可能是因为 Spring Boot 确实返回了正确的标头......

谢谢您的帮助!

java spring-boot spring-security cors tomcat10
2个回答
0
投票

我遇到了同样的问题,因为我没有正确配置 CORS。这是我的配置:

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {

    http
        .csrf().disable()
        .cors(c -> c.configurationSource(request -> {
            CorsConfiguration cors = new CorsConfiguration();
            cors.setAllowedOrigins(List.of("*"));
            cors.setAllowedMethods(List.of("GET","POST", "PUT", "DELETE", "OPTIONS"));
            cors.setAllowedHeaders(List.of("*"));
            cors.setExposedHeaders(List.of(HttpHeaders.AUTHORIZATION, HttpHeaders.CONTENT_TYPE));
            return cors;
        }))
        .authorizeHttpRequests()
        ...

这将允许为任何来源提供服务。也适用于任何方法。


0
投票

我相信这可以帮助你解决这个问题。

corsConfigurationSource 中替换此

configuration.setAllowedOrigins(Collections.singletonList("http://goods.example.com"));

有了这个

configuration.addAllowedOriginPattern("*");
© www.soinside.com 2019 - 2024. All rights reserved.