CORS重定向Origin为Null问题排查及解决方案咨询
问题原因
这是浏览器的安全限制导致的:当跨源请求被重定向到新的源时,浏览器会自动将后续重定向请求的Origin设为null,目的是防止敏感Origin信息被泄露到未授权的第三方。你的场景里,初始请求从1.example.com到example.com属于同主域的跨子域请求,但重定向到2.example.com后,浏览器触发了这个安全规则,导致Origin变为null,而2.example.com的服务器只允许https://1.example.com作为合法Origin,因此请求被拒绝。
可行解决方案
1. 临时允许null Origin(谨慎使用)
如果2.example.com的服务器可以修改配置,直接在响应头中添加:
Access-Control-Allow-Origin: null
同时保留Access-Control-Allow-Credentials: true。注意:这种方式存在安全风险,因为null Origin可能来自本地文件或其他不可信来源,仅适合测试或完全可控的内部场景。
2. 前端接管重定向逻辑
让服务器不要返回302状态码,而是返回包含目标URL的JSON响应。前端拿到URL后,主动发起请求或跳转,此时Origin会保持为1.example.com。
- 服务器返回示例:
{"redirect_to": "https://2.example.com/test"} - 前端代码示例:
fetch('https://example.com/redirector?url=https://2.example.com/test', { credentials: 'include' }) .then(res => res.json()) .then(data => { // 主动发起新请求 return fetch(data.redirect_to, { credentials: 'include' }); // 或者直接跳转页面 // window.location.href = data.redirect_to; });
3. 动态匹配合法Origin
在服务器端配置动态的CORS规则,允许所有*.example.com下的子域作为合法Origin。以Nginx为例:
if ($http_origin ~* ^https?://.*\.example\.com$) { add_header Access-Control-Allow-Origin $http_origin; add_header Access-Control-Allow-Credentials true; add_header Vary Origin; }
这样不管是哪个子域发起的请求,只要属于example.com主域,都会被允许,从根源上避免Origin不匹配的问题。
附请求日志详情:
#Redirector is used for testing. Request URL: https://example.com/redirector?url=https://2.example.com/test #Response Headers HTTP/1.1 302 Found Server: nginx/1.25.2 Date: Thu, 07 Sep 2023 11:56:06 GMT Content-Type: text/html; charset=UTF-8 Content-Length: 0 Connection: keep-alive Vary: User-Agent Expires: Thu, 19 Nov 1981 08:52:00 GMT Cache-Control: no-store, no-cache, must-revalidate Pragma: no-cache Access-Control-Allow-Credentials: true Access-Control-Allow-Origin: https://1.example.com Access-Control-Allow-Headers: X-Requested-With, Content-Type Location: https://2.example.com/test Set-Cookie: SES=2bb6e51d371052a7ee0c60a4e5f447f3; path=/; domain=.example.com; secure; HttpOnly;SameSite=None #Request headers GET /redirector?url=https://2.example.com/test HTTP/1.1 Accept: */* Accept-Encoding: gzip, deflate, br Accept-Language: en-US,en;q=0.9,ar;q=0.8 Cache-Control: no-cache Connection: keep-alive Host: example.com Origin: https://1.example.com Pragma: no-cache Referer: https://1.example.com/ Sec-Fetch-Dest: empty Sec-Fetch-Mode: cors Sec-Fetch-Site: same-site User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36 sec-ch-ua: "Chromium";v="116", "Not)A;Brand";v="24", "Google Chrome";v="116" sec-ch-ua-mobile: ?0 sec-ch-ua-platform: "macOS" # Redirect Call would be to /test https://2.example.com/test #Response Headers HTTP/1.1 302 Found Server: nginx/1.25.2 Date: Thu, 07 Sep 2023 11:56:06 GMT Content-Type: text/html; charset=UTF-8 Content-Length: 0 Connection: keep-alive Vary: User-Agent Expires: Thu, 19 Nov 1981 08:52:00 GMT Cache-Control: no-store, no-cache, must-revalidate Pragma: no-cache Access-Control-Allow-Credentials: true Access-Control-Allow-Origin: https://1.example.com Access-Control-Allow-Headers: X-Requested-With, Content-Type, Authorization Location: https://www.example.com/login?redirect_url=https%3A%2F%2F2.example.com%2Ftest Set-Cookie: SES=3f660180a56712e99b933d108ca9ade9; path=/; domain=.example.com; secure; HttpOnly;SameSite=None #Request headers GET /test HTTP/1.1 Accept: */* Accept-Encoding: gzip, deflate, br Accept-Language: en-US,en;q=0.9,ar;q=0.8 Cache-Control: no-cache Connection: keep-alive Host: 2.example.com Origin: null Pragma: no-cache Referer: https://1.example.com/ Sec-Fetch-Dest: empty Sec-Fetch-Mode: cors Sec-Fetch-Site: same-site User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36 sec-ch-ua: "Chromium";v="116", "Not)A;Brand";v="24", "Google Chrome";v="116" sec-ch-ua-mobile: ?0 sec-ch-ua-platform: "macOS"
内容的提问来源于stack exchange,提问作者mayartahina
相关产品推荐
相关产品推荐

