Safari出现CORS跨域错误,Chrome正常,求排查解决方法
我有一个React Web应用,会调用Express Web服务器的接口。在Chrome中访问该应用时一切正常,但在Safari中访问时出现错误:
XMLHttpRequest cannot load https://subdomain.example.com/path due to access control checks.
在网络面板中可以看到失败的请求详情:
Summary URL: https://api.example.com/path Status: — Source: — Initiator: 2.6ac8194f.chunk.js:2:223735 Request Accept: application/json, text/plain, */* Authorization: Bearer [...] Origin: https://app.example.com Referer: https://app.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/605.1.15 (KHTML, like Gecko) Version/17.5 Safari/605.1.15 Response No response headers
我用Express的cors包配置跨域,初始代码如下:
const express = require('express'); const cors = require('cors'); const app = express(); (async () => { app.use(cors()); app.use('/path', [ require('./apis/path'), ]); }()
了解到Safari的CORS策略更严格,不能用通配符且必须指定带协议的源,于是修改配置为:
app.use(cors({ origin: ['https://app.example.com', 'https://other-app.example.com'] }));
但错误仍然存在,请问还遗漏了什么配置?
配置凭证支持:你的请求带
Authorization头,属于带凭证的请求,Safari对此类请求的CORS校验更严格。需要在cors配置中显式开启credentials: true,同时确保React端请求也开启凭证传递:
Express端修改:app.use(cors({ origin: ['https://app.example.com', 'https://other-app.example.com'], credentials: true }));React端(以axios为例):
axios.get('https://api.example.com/path', { withCredentials: true });若用fetch:
fetch('https://api.example.com/path', { credentials: 'include' });确保预检请求正常处理:Safari会严格检查OPTIONS预检请求的响应,
cors包虽自动处理,但如果路由有自定义中间件,可能拦截OPTIONS请求。可以单独配置OPTIONS方法的处理:app.options('*', cors({ origin: ['https://app.example.com', 'https://other-app.example.com'], credentials: true }));检查Cookie的Same-Site属性:如果请求依赖Cookie,需确保Cookie的
SameSite设为None,且配合Secure属性(仅HTTPS环境可用),避免被Safari拦截。验证源的完全匹配:确认配置的源
https://app.example.com和请求头中的Origin完全一致,包括端口号(若React应用带端口运行,需同步添加到配置的源列表)。清除Safari缓存:Safari可能缓存旧的CORS策略或Cookie,导致新配置不生效。尝试清除浏览器缓存、Cookie,或用隐私模式测试。
内容的提问来源于stack exchange,提问作者Bethany

