预检成功,但取消了带有授权标头的响应

Posted

技术标签:

【中文标题】预检成功,但取消了带有授权标头的响应【英文标题】:Successful preflight, but cancelled responses with authorization headers 【发布时间】:2018-08-11 09:18:45 【问题描述】:

我正在开发一个与 Express 服务器通信的 Ionic 应用程序。在最后一个发布周期之前,一切都运行良好。部署后,我们一半的 API 调用在我们的实时服务器上停止正常运行。

我已将问题范围缩小到包含 Authorization 标头的请求。所有其他不需要该 Auth 标头的请求都可以正常工作,但是具有 auth 的请求在 prefilght 选项检查中返回 204,但随后实际请求被取消。控制台在 Firefox 中提供 0 - "isTrusted":true,在 Chrome 中提供 net::ERR_CONNECTION_CLOSED。据我所知,实际的请求甚至没有到达服务器,响应只是一个空的响应对象,状态码为:0。

所以我不知道从哪里开始,我一直在阅读有关 CORS 问题的信息,但我们最近没有更改任何标题或配置。

此外,令人疯狂的是,我们在 iPhone 5 上的测试版本运行良好,但在桌面网络浏览器和 android 上却失败了。可能是旧版本的 Safari Mobile?

这是一个使用 auth 标头失败的示例 GET 请求。

PREFLIGHT REQUEST:
Host: app.example.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:58.0) Gecko/20100101 Firefox/58.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Access-Control-Request-Method: GET
Access-Control-Request-Headers: app-api-key,authorization
Origin: http://localhost:8100
Connection: keep-alive

PREFLIGHT RESPONSE:
server: nginx/1.10.3 (Ubuntu)
date: Sat, 03 Mar 2018 06:14:39 GMT
x-dns-prefetch-control: off
x-download-options: noopen
x-xss-protection: 1; mode=block
access-control-allow-origin: http://localhost:8100
vary: Origin, Access-Control-Request-Headers
access-control-allow-credentials: true
access-control-allow-methods: GET,HEAD,PUT,PATCH,POST,DELETE
access-control-allow-headers: app-api-key,authorization
x-frame-options: SAMEORIGIN, SAMEORIGIN
x-content-type-options: nosniff, nosniff
X-Firefox-Spdy: h2

GET REQUEST HEADERS:
Accept  application/json, text/plain, */*
Accept-Encoding gzip, deflate, br
Accept-Language en-US,en;q=0.5
app-api-key: fakeapikeyhere
Authorization: JWT fakejwtauthtokenhere
Connection: keep-alive
Host: app.example.com
Origin: http://localhost:8100
Referer: http://localhost:8100/?ionicpl…tp://localhost:8100/ionic-lab
User-Agent: Mozilla/5.0 (Windows NT 10.0; …) Gecko/20100101 Firefox/58.0

【问题讨论】:

【参考方案1】:

HTTP/2 对 HTTP 标头非常严格,并且当这些标头格式错误时将不允许请求。所以这里可能还是有问题,但是 HTTP/1.1 只是稍微宽容了一点。

This post 提供了有关如何通过使用 Chrome 中的 chrome://net-internals/#events 页面然后查看 HTTP2_SESSION 来调试任何 HTTP 标头问题的良好信息。虽然这更适用于接收错误的标头,而您的问题似乎在于发送最后一个请求。

您的标题似乎肯定有问题:

x-frame-options: SAMEORIGIN, SAMEORIGIN
x-content-type-options: nosniff, nosniff

为什么重复这些值?

GET REQUEST HEADERS:
Accept  application/json, text/plain, */*
Accept-Encoding gzip, deflate, br
Accept-Language en-US,en;q=0.5

为什么这些值在标头名称后没有冒号?

不确定这两个是拼写错误还是复制/粘贴错误,但现在看起来有点可疑。

此外,在 HTTP/2 下,所有标头名称都应为小写,尽管大多数浏览器会自动为您转换。标题值可以是大写、小写或混合大小写。

希望这能让您进一步调查。

【讨论】:

+1 这些都是好点。我要调查其中的一些。我认为重复是由使用头盔和 cors npm 包引起的。不确定是否缺少分号。 重复的标题通常不会导致问题,但很奇怪。缺少冒号(不是分号)会导致 HTTP/2 出现问题。【参考方案2】:

所以我已经解决了一半。这实际上是某种 HTTP/2.0 问题。我认为最近重新启动我的 Digital Ocean 服务器时,某些东西得到了更新或启用。某些不支持 HTTP/2.0 的浏览器可以正常工作,而其他浏览器则不能。我不完全确定为什么我的调用在 HTTP/2.0 上不起作用,但这是一个单独的问题。

如果您正在寻找调试,如果这是您的问题,您可以尝试运行 chrome 并禁用 http2 并查看它是否开始工作。从 chrome 目录运行:

./chrome.exe --disable-http2

通过从我的 NGINX 配置中删除 http2 解决了我的具体情况。

跑步:

sudo nano /etc/nginx/sites-available/default

并编辑以下内容:

# SSL Config
listen 443 ssl http2 default_server; # <- Removed the http2
listen [::]:443 ssl http2 default_server; # <- Removed the http2

然后重启

sudo systemctl restart nginx

【讨论】:

以上是关于预检成功,但取消了带有授权标头的响应的主要内容,如果未能解决你的问题,请参考以下文章

CORS,防止带有授权标头的请求预检

预检响应中的 Access-Control-Allow-Headers 不允许请求标头字段授权

被 CORS 阻止:预检响应中的 Access-Control-Allow-Headers 不允许请求标头字段授权

IBM Watson Conversation API:“预检响应中的 Access-Control-Allow-Headers 不允许请求标头字段授权”

预检响应中的 Access-Control-Allow-Headers 不允许请求标头字段授权。 (nginx)

被 CORS 策略阻止:预检响应中的 Access-Control-Allow-Headers 不允许请求标头字段授权