javascript - 在使用 CORS 的情况下,Edge 浏览器不会重定向呼叫
问题描述
请帮我找到适合 Edge 浏览器的解决方案。
我发现在 GET 和 POST 请求的 HTTP 302 Found 响应的情况下,Edge 浏览器不遵循 Location 标头。
简而言之,相同的代码(参见下面的解释):
- 在 FF/Chrome 中完美运行(所有标头都为初始调用设置,标头/cookie 也为所有重定向调用设置和发送)
- Edge 浏览器忽略 Location 标头/HTTP 302 响应代码(根本没有重定向)。
- IE 11 浏览器会忽略我们在重定向调用中为初始调用 (Content-Type) 设置的标头
打开的页面:https ://example.com
使用自定义标头集对https://some-service.io/login进行异步 GET 调用
Content-Type = application/json; charset=utf-8
X-Header = http://some-service.io/xxx-yyy-zzz
注意:页面和服务使用不同的域
由于 CORS 启用了 withCredentials,数据属性有一个空对象(用于 axios 调用)或一些虚拟数据(用于 javascript 调用),因为我们在 Chrome/FF 中遇到了重定向调用标头的问题:
Javascript 版本
function httpGetAsync(url, method, callback) {
var xmlHttp = new XMLHttpRequest();
xmlHttp.onreadystatechange = function ()
{
if (xmlHttp.readyState == XMLHttpRequest.DONE && xmlHttp.status == 200) {
console.log('DONE');
callback(xmlHttp.readyState + ':' + xmlHttp.status + ':' + xmlHttp.response);
return;
}
console.log(xmlHttp.readyState + ':' + xmlHttp.status + ':' + xmlHttp.response);
var headers = xmlHttp.getAllResponseHeaders();
console.log('headers: ' + headers.toString());
}
xmlHttp.open(method, url, true); // true for asynchronous
xmlHttp.withCredentials = true;
xmlHttp.setRequestHeader('Accept', 'application/json');
xmlHttp.setRequestHeader('Content-Type', 'application/json;charset=UTF-8');
xmlHttp.setRequestHeader('X-Header', 'https://some-service.io/xxx-yyy-zzz');
xmlHttp.send("foo=bar&lorem=ipsum");
}
httpGetAsync('https://some-service.io/login', 'GET', function (response) {
console.log(response);
});
AXIOS 版本
...
defaultHeaders['Content-Type'] = 'application/json;charset=UTF-8';
defaultHeaders['X-Header'] = 'https://some-service.io/xxx-yyy-zzz';
...
axios({
method: 'GET',
url: 'https://some-service.io/login',
withCredentials: true,
headers: defaultHeaders,
data: {}
}).then(response => {
...
- 服务器以 HTTP 302 响应,响应中带有 Set-Cookie 和 Location: https://some-service.io/login/auth标头,我们需要将原始标头和通过重定向调用设置的 cookie 发送到 https:// some-service.io/login/auth
对于对https://some-service.io/login/auth的重定向调用,服务器响应 HTTP 200,如果在请求标头中设置了 Content-Type,则返回 json-object:
- Chrome/FF 完美运行,遵循重定向,初始调用的标头也可用于重定向调用,HTTP 200 返回有效的 json-object
- 边缘浏览器根本不遵循 Location 标头值
- IE 11 浏览器遵循 Location 标头中的重定向 url,但在初始调用中没有设置标头(添加仅用于比较)
原始 HTTP
边缘
-- 选项(预检)
OPTIONS https://some-service.io/login HTTP/1.1
Origin: https://example.com
Referer: https://example.com?uuid=38db98a3-f6f0-11e9-b2be-6814011b702b
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.18362
Access-Control-Request-Headers: content-type,database,dictionarydomain,language,site,x-referer-epay
Access-Control-Request-Method: GET
Accept: */*
Accept-Language: en-US,en;q=0.8,cs;q=0.6,ru;q=0.4,uk;q=0.2
Accept-Encoding: gzip, deflate, br
Host: some-service.io
Content-Length: 0
DNT: 1
Connection: Keep-Alive
Cache-Control: no-cache
-- 获取请求
GET https://some-service.io/login HTTP/1.1
Origin: https://example.com
Referer: https://example.com?uuid=38db98a3-f6f0-11e9-b2be-6814011b702b
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.18362
Accept: application/json, text/plain, */*
Accept-Language: en-US,en;q=0.8,cs;q=0.6,ru;q=0.4,uk;q=0.2
Content-Type: application/json;charset=UTF-8
X-Header: https://some-service.io/xxx-yyy-zzz
Accept-Encoding: gzip, deflate, br
Host: some-service.io
DNT: 1
Connection: Keep-Alive
-- 获取响应
HTTP/1.1 302 Found
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: https://example.com
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Date: Tue, 10 Dec 2019 12:26:08 GMT
Expires: 0
Location: https://some-service.io/login/auth
Pragma: no-cache
Set-Cookie: JSESSIONID=CC10DD73C968C42C5A007D27342BF0B5; Path=/; Secure
Set-Cookie: __VCAP_ID__=32ee654d-2947-49e4-4909-9bc7; Path=/; HttpOnly; Secure
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-Vcap-Request-Id: ef27c9ae-fa5b-45b6-5c6a-9537b159e533
X-Xss-Protection: 1; mode=block
Content-Length: 0
Connection: keep-alive
-- GET 重定向呼叫请求(https://some-service.io/login/auth,缺失)
铬合金
-- 选项(预检)
OPTIONS https://some-service.io/login HTTP/1.1
Host: some-service.io
Connection: keep-alive
Access-Control-Request-Method: GET
Origin: https://example.com
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
Access-Control-Request-Headers: content-type,database,dictionarydomain,language,site,x-referer-epay
Accept: */*
Sec-Fetch-Site: cross-site
Sec-Fetch-Mode: cors
Referer: https://example.com?uuid=38db98a3-f6f0-11e9-b2be-6814011b702b
Accept-Encoding: gzip, deflate, br
Accept-Language: en,ru-RU;q=0.9,ru;q=0.8,en-US;q=0.7,en-GB;q=0.6
-- 获取请求
GET https://some-service.io/login HTTP/1.1
Host: some-service.io
Connection: keep-alive
Origin: https://example.com
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
Accept: application/json, text/plain, */*
X-Header: https://some-service.io/xxx-yyy-zzz
Sec-Fetch-Site: cross-site
Sec-Fetch-Mode: cors
Referer: https://example.com?uuid=38db98a3-f6f0-11e9-b2be-6814011b702b
Accept-Encoding: gzip, deflate, br
Accept-Language: en,ru-RU;q=0.9,ru;q=0.8,en-US;q=0.7,en-GB;q=0.6
Cookie: JSESSIONID=998B805DAF1BBA4C76AB930702C49131; __VCAP_ID__=a3ed6e06-6e23-43ad-469a-e848
-- 获取响应
HTTP/1.1 302 Found
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: https://example.com
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Date: Tue, 10 Dec 2019 10:33:02 GMT
Expires: 0
Location: https://some-service.io/login/auth
Pragma: no-cache
Set-Cookie: __VCAP_ID__=32ee654d-2947-49e4-4909-9bc7; Path=/; HttpOnly
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-Vcap-Request-Id: e207bdaa-20a6-48a1-7f97-b0688d2f1f98
X-Xss-Protection: 1; mode=block
Content-Length: 0
Connection: keep-alive
-- GET请求重定向呼叫(https://some-service.io/login/auth)
GET https://some-service.io/login/auth HTTP/1.1
Host: some-service.io
Connection: keep-alive
Origin: https://example.com
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
Accept: application/json, text/plain, */*
Database: master
X-Header: https://some-service.io/xxx-yyy-zzz
Sec-Fetch-Site: cross-site
Sec-Fetch-Mode: cors
Referer: https://example.com?uuid=38db98a3-f6f0-11e9-b2be-6814011b702b
Accept-Encoding: gzip, deflate, br
Accept-Language: en,ru-RU;q=0.9,ru;q=0.8,en-US;q=0.7,en-GB;q=0.6
Cookie: JSESSIONID=998B805DAF1BBA4C76AB930702C49131; __VCAP_ID__=32ee654d-2947-49e4-4909-9bc7
-- 获取响应
HTTP/1.1 200 OK
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: https://example.com
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Content-Type: application/json;charset=UTF-8
Date: Tue, 10 Dec 2019 10:35:35 GMT
Expires: 0
Pragma: no-cache
Set-Cookie: __VCAP_ID__=a3ed6e06-6e23-43ad-469a-e848; Path=/; HttpOnly
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-Vcap-Request-Id: ad084e82-1038-4953-5f40-cfcf4f4c10d3
X-Xss-Protection: 1; mode=block
Content-Length: 16
Connection: keep-alive
{"some-value":0}
笔记
- Edge 和 Chrome 的主要区别——这两个标头
Sec-Fetch-Site: cross-site
Sec-Fetch-Mode: cors
- 边缘/18.18362
- 铬/78.0.3904.108
解决方案
为了缓解不同浏览器的 CORS 实现差异,我决定将 CORS 请求从 FE 端移动到 BE 端。实现了小型透明代理来服务从 FE 到 BE 的请求,并使用 RestClient(或 HttpClient)组件从 BE 调用 Service,与从 FE 到 Service 的直接调用相比,该组件与 CORS 和重定向调用完美配合。
推荐阅读
- c++ - cpp修改中的引用变量
- ios - 应用程序从挂起状态终止后,应用程序界面快照短暂闪烁
- oracle - ORA-06508 调用远程数据库上的过程时
- qt - QML 将信号连接到功能
- asterisk - Asterisk Dialplan AGI 脚本未执行(可能是 Asterisk 权限问题?)
- php - MailChimp API v3 - 无法修补/更新?
- c++ - Asio TCP 服务器在 DLL 卸载时崩溃
- java - API < 21 的 Android 复选框按钮样式
- dialogflow-es - Google Dialogflow V2 - 身份验证 - 访问令牌
- javascript - Sublime Text Ctrl + B 不会显示输出(JavaScript)