Access-Control-Allow-Origin与origin一致但浏览器仍拦截访问的原因排查
问题根因
这是浏览器处理跨域重定向的标准行为导致的:
- 前端发起对
media.foo.bar.com的跨域请求,预检和首次正式请求的CORS校验都通过,但media返回302重定向到api.foo.bar.com media.foo.bar.com和api.foo.bar.com属于不同源,这种跨源重定向场景下,浏览器自动跟随重定向发起对api子域的请求时,不会重新发起OPTIONS预检,且部分浏览器会将该请求的Origin头设置为null- 你当前Express的CORS配置仅允许了SPA的正式域名,没有处理
Origin为null的情况,因此api子域返回的Access-Control-Allow-Origin头和请求的nullOrigin不匹配,触发跨域拦截。你之前只检查了media子域的响应头,没有查看重定向后api子域的响应头,所以会误认为头是匹配的。
解决方案
你可以根据业务场景选择以下任意一种方案:
- 避免跨源重定向
最简单的方案是把重定向逻辑迁到前端处理:media子域不返回302,而是以200状态码将目标地址放在响应体中,前端拿到地址后主动发起对api子域的请求,两次请求会各自走正常的CORS预检流程,不会触发重定向异常。 - 调整CORS配置适配重定向场景
如果必须保留302重定向,可以在api子域的Express CORS配置中,增加对nullOrigin的允许规则,注意不要使用通配符*(你开启了Access-Control-Allow-Credentials: true,通配符规则不生效),配置示例:const allowedOrigins = ['https://foo.bar.com', 'null']; app.use(cors({ origin: (origin, callback) => { if (allowedOrigins.includes(origin)) { callback(null, true); } else { callback(new Error('Not allowed by CORS')); } }, credentials: true })); - NGINX层统一入口
在NGINX入口层做路径转发,将/api、/media等路径分别转发到对应的后端服务,前端所有请求都指向同一个源,从根源上避免跨域问题,自然不会出现重定向跨源的异常。
内容的提问来源于stack exchange,提问作者Bruno Brant
相关产品推荐
相关产品推荐

