rest - 当 POST 请求没有正文并且服务器响应是 403 禁止错误时 CORS 失败

标签 rest tomcat cors

我正在处理的应用程序将请求从运行在 localhost:80 上的 apache 服务器发送到运行在 localhost:8080 上的 tomcat 服务器,这正在创建一个跨源场景。当应用程序发送带有正文的 POST 请求时,将发送飞行前请求,响应包含所有必要的 header ,然后发送实际请求并显示成功。如果我在没有正文的情况下发送相同的请求,则不会发送飞行前请求并且我会收到

'Access to XMLHttpRequest at 'http://localhost:8080/webapp/api' from origin 'http://localhost' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

我已经将 CORS 过滤器添加到 Tomcat 并对其进行了配置:

        <filter-name>CorsFilter</filter-name>
        <filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
        <init-param>
          <param-name>cors.allowed.origins</param-name>
          <param-value>http://localhost</param-value>
        </init-param>
        <init-param>
         <param-name>cors.supportedMethods</param-name>
            <param-value>GET, POST, HEAD, PUT, DELETE</param-value>
        </init-param>
        <init-param>
            <param-name>cors.support.credentials</param-name>
            <param-value>true</param-value>
        </init-param>
        <init-param>
            <param-name>cors.allowed.headers</param-name>
            <param-value>Content-Type,X-Requested-With,accept,Origin,Access-Control-Request-Method,Access-Control-Request-Headers</param-value>
        </init-param>
        <init-param>
            <param-name>cors.exposed.headers</param-name>
            <param-value>Access-Control-Allow-Origin,Access-Control-Allow-Credentials</param-value>
        </init-param>
        <init-param>
            <param-name>cors.preflight.maxage</param-name>
            <param-value>10</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>CorsFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

以下是一些 fiddler 输出: 帖子中没有正文

请求

POST http://localhost:8080/webapp/api/cart/promoremove/null?school=localhost HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Content-Length: 0
Accept: application/json, text/plain, */*
Origin: http://localhost
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36
Sec-Fetch-Site: same-site
Sec-Fetch-Mode: cors
Referer: http://localhost/cart-home
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Cookie: JSESSIONID=DF1A170A1B38AD7B2EFDC70A742027B8; hazelcast.sessionId=HZ90788223E83048308A167BE8514D5649; NG_TRANSLATE_LANG_KEY=%22en%22; JSESSIONID=205B812430E4261E2E2999AED6652E1D; liveagent_oref=; liveagent_ptid=4a8955a7-df01-4e22-8f77-16cabf542a11; liveagent_sid=95a17ee7-44da-480e-9f80-0fce17de4ecb; liveagent_vc=3; SESS49960de5880e8c687434170f6476605b=tumGvaRrAVNtDjAwOmMVuNivVnoZLt3muLr8KjAcyj4; ceshopCartUUID=null

响应

HTTP/1.1 403 Forbidden
Server: Apache-Coyote/1.1
Access-Control-Allow-Methods: POST, GET, OPTIONS, DELETE
Access-Control-Max-Age: 3600
Access-Control-Allow-Headers: origin,x-requested-with,access-control-request-headers,content-type,access-control-request-method,accept
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Application-Context: application:dev:8080
Content-Type: text/plain;charset=UTF-8
Date: Thu, 05 Dec 2019 22:59:59 GMT
Content-Length: 0 

还有 body

请求

POST http://localhost:8080/webapp/api/cart/promoremove/null?school=localhost HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Content-Length: 15
Accept: application/json, text/plain, */*
Origin: http://localhost
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36
Content-Type: application/json;charset=UTF-8
Sec-Fetch-Site: same-site
Sec-Fetch-Mode: cors
Referer: http://localhost/cart-home
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Cookie: JSESSIONID=DF1A170A1B38AD7B2EFDC70A742027B8; hazelcast.sessionId=HZ90788223E83048308A167BE8514D5649; NG_TRANSLATE_LANG_KEY=%22en%22; JSESSIONID=205B812430E4261E2E2999AED6652E1D; liveagent_oref=; liveagent_ptid=4a8955a7-df01-4e22-8f77-16cabf542a11; liveagent_sid=95a17ee7-44da-480e-9f80-0fce17de4ecb; liveagent_vc=3; SESS49960de5880e8c687434170f6476605b=tumGvaRrAVNtDjAwOmMVuNivVnoZLt3muLr8KjAcyj4; ceshopCartUUID=null

{"some":"body"}

响应

HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Access-Control-Allow-Methods: POST, GET, OPTIONS, DELETE
Access-Control-Max-Age: 3600
Access-Control-Allow-Headers: origin,x-requested-with,access-control-request-headers,content-type,access-control-request-method,accept
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Application-Context: application:dev:8080
Access-Control-Allow-Origin: http://localhost
Access-Control-Allow-Credentials: true
Access-Control-Expose-Headers: Access-Control-Allow-Origin,Access-Control-Allow-Credentials
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Date: Thu, 05 Dec 2019 23:08:34 GMT

b75
{"cartUUID":null}

那么,有没有人知道为什么当请求没有正文时不返回 Allow-Origin-Headers 并因此失败。

最佳答案

遇到同样的问题后,我确实发现这实际上是 Tomcat CORS 过滤器所做的。这是 CorsFilter 的相关部分:

        CORSRequestType requestType = CORSRequestType.INVALID_CORS;
...
                    } else if ("POST".equals(method)) {
                        String mediaType = getMediaType(request.getContentType());
                        if (mediaType != null) {
                            if (SIMPLE_HTTP_REQUEST_CONTENT_TYPE_VALUES
                                    .contains(mediaType)) {
                                requestType = CORSRequestType.SIMPLE;
                            } else {
                                requestType = CORSRequestType.ACTUAL;
                            }
                        }
                    }

如果方法是 POST,但没有 Content-Type 头,请求类型仍然是 INVALID_CORS。在过滤器代码中向下一点会导致错误代码 403。

所以,这就是导致 403 的原因,但我不确定这里是否处理正确。

由于我的用例是一个必须部署在多个版本的 tomcat 上的应用程序,即使这在某个时间点被更改/修复,我们也会依赖于这个最新的 tomcat 版本。我想避免的事情,所以我要么将我自己的 CorsFilter 版本与我们的应用程序打包在一起,要么更改 API 定义,以便它发送 Content-Type。

关于rest - 当 POST 请求没有正文并且服务器响应是 403 禁止错误时 CORS 失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59204624/

相关文章:

java - 从 Java 函数返回环境变量,并在 Jenkins 中设置相同的环境变量以运行构建

javascript - Angular $HTTP 响应语法错误 : Unexpected token E

c# - 确定 RESTful API 中有意义的 HTTP 响应代码以进行业务规则验证

java - 图片直接从客户端上传到远程服务器? Spring / Tomcat

http - 为什么 HTTP 每个套接字只能处理一个待处理的请求?

tomcat - 使用 tomcat 配置 SSL

java - 尝试运行 Apache-Tomcat : JRE_HOME variable is not defined correctly 的 startup.bat 时出错

proxy - 将 CORS 或 nginx proxy_pass 用于 RESTful 客户端 - 服务器应用程序是否更好?

javascript - Javascript 和 .NET Minimal API 中的 CORS 策略

javascript - XMLHttpRequest 问题 : Cross origin requests are only supported for protocol schemes: http, 数据、chrome、chrome 扩展、https