AWS 中的 403 OPTIONS Cors 错误,预检请求

Posted

技术标签:

【中文标题】AWS 中的 403 OPTIONS Cors 错误,预检请求【英文标题】:403 OPTIONS Cors error in AWS, preflight requests 【发布时间】:2020-04-09 23:58:44 【问题描述】:

我已将 React JS + Spring boot 应用程序部署到 AWS 云。我的 React JS 项目存储在 CloudFront 中使用的 S3 存储桶中。 Spring boot 应用部署到 Elastic Beanstalk 服务。

当我尝试从 CloudFront 分配向后端发出任何请求时,我收到 403 错误 OPTIONS Cors,如下所示:

Access to fetch at 'https://api.divelog.eu/getuserdata/eyJhbGciOiJIUzUxMiJ9.eyJsb2dnZWRB' from origin 'https://divelog.eu' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

我已经在 Spring Boot 的服务器端启用了 CORS:

@Component
public class CustomCorsFilter extends OncePerRequestFilter 

@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException 
    response.setHeader("Access-Control-Allow-Origin", "*");
    response.setHeader("Access-Control-Allow-Methods", "GET, POST, PATCH, PUT, DELETE, OPTIONS");
    response.setHeader("Access-Control-Max-Age", "3600");
    response.setHeader("Access-Control-Allow-Headers", "Origin, Content-Type, Allow, authorization, content-type, xsrf-token");
    response.addHeader("Access-Control-Expose-Headers", "xsrf-token");
    if ("OPTIONS".equals(request.getMethod())) 
        response.setStatus(HttpServletResponse.SC_OK);
     else 
        filterChain.doFilter(request, response);
    



also 

@Configuration
@EnableWebSecurity
public class SocialConfig extends WebSecurityConfigurerAdapter 

@Override
protected void configure(HttpSecurity http) throws Exception 
    http.cors().and()
            .csrf().disable()
            .antMatcher("/**")
            .authorizeRequests()
            .antMatchers("/", "/login**", "/webjars/**", "/error**",
                    "/signin", "/getuserdata/**", "/add/marker/**", "/get/markers/**", "/delete/marker/**/**",
                    "/logout/**", "/add/logbook/**/**", "/get/logbook/**", "/logbook/**/**", "/**/**", "/edit/logbook/**/**",
                    "/pdf/logbook/**/**", "/add/topic", "/get/topic/posts/**", "/add/post", "/delete/post/**/**", "/post/**/**",
                    "/delete/post/file/**/**", "/get/topic/number/comments/**/**", "/update/topic/number/displays/**",
                    "/topic/likes/vote/**/**", "/update/topic/**", "/callback", "/signin", "/oauth/request_token")
            .permitAll()
            .anyRequest()
            .authenticated()

            .and()
            .addFilterBefore(new CorsFilter(), ChannelProcessingFilter.class);


在 React JS 项目中,我通过 fetch 和 axios 传递这些标头:Accept、Content-Type。

我在 AWS S3 存储桶中用于 Spring boot 和 React JS 的 CORS 设置为:

<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
<AllowedMethod>PUT</AllowedMethod>
<AllowedMethod>POST</AllowedMethod>
<AllowedMethod>DELETE</AllowedMethod>
<AllowedHeader>*</AllowedHeader>
</CORSRule>
</CORSConfiguration>

当我尝试通过 Postman 访问端点时,部署到 Elastic Beanstalk 的 Spring Boot 应用程序运行良好,但只有当我尝试从 S3 存储桶实例向后端 API 发出请求时,才会收到 cors 错误。

我在弹性 beanstalk 实例的负载均衡器中添加了 443 和 80 HTTP HTTPS 端口的侦听器。

您知道为什么我仍然会收到此错误吗?

    CloudFront 行为

【问题讨论】:

【参考方案1】:

您必须将此 JSON 配置添加到 S3 存储桶的权限。

[
    
        "AllowedHeaders": [
            "Authorization",
            "Content-Range",
            "Accept",
            "Content-Type",
            "Origin",
            "Range"
        ],
        "AllowedMethods": [
            "GET",
            "POST",
            "PUT"
        ],
        "AllowedOrigins": [
            "*"
        ],
        "ExposeHeaders": [
            "Content-Range",
            "Content-Length",
            "ETag"
        ],
        "MaxAgeSeconds": 3000
    
]

【讨论】:

【参考方案2】:

我认为您的后端 api.divelog.eu 仍然没有设置Access-Control-Allow-Origin,您可以在状态码 403 的响应中看到响应标头中仍然没有Access-Control-Allow-Origin

此标头必须从后端发送到客户端浏览器以防止 cors。

参考: https://javascript.info/fetch-crossorigin

【讨论】:

我应该在哪里设置这个 cors ?我在服务器端启用了 cors。那么,我在 Spring Boot 中的配置可能不起作用? 当我将 React JS 获取请求更改为 mode: 'no-cors' -> 所有请求的标头都在响应标头中。它看起来像一个错误。我认为这应该是我提出请求的时候,但我不想使用模式:'no-cors'。当我尝试不带 cors 的请求时,我得到 net::ERR_ABORTED。 当您将客户端请求标头 Sec-Fetch-Mode 更改为 no-cors 时,您收到了来自后端的响应? 我发现错误。我注释掉了这一行 .addFilterBefore(new CorsFilter(), ChannelProcessingFilter.class);在配置方法中,一切正常。谢谢回复!

以上是关于AWS 中的 403 OPTIONS Cors 错误,预检请求的主要内容,如果未能解决你的问题,请参考以下文章

无服务器框架 AWS REST API Gateway - 403 CORS 错误

尽管将 AWS 静态文件路径添加到 CORS_ORIGIN_WHITELIST django-cors-headers,但出现 403 错误

具有自定义授权者和 CORS 间歇性 200 然后 403 然后 200 的 AWS API 网关 ...奇怪

AWS Api Gateway 仅在 OPTIONS 调用时不响应 CORS 标头

AWS API Gateway CORS 对 OPTIONS 正常,对 POST 失败

CORS 问题:预检响应具有无效的 HTTP 状态代码 403