背景:
CORS,即 Cross-Origin Resource Sharing (跨源资源共享)。当一个资源从与该资源本身所在服务器不同的域、协议或端口发起请求时,就会触发跨域。比如,http://domain-a.com的 HTML 页面通过 <img> 的 src 请求http://domain-b.com/image.jpg,需要针对domain-b.com域名配置允许来自domain-a.com的访问。这是由于浏览器的同源策略造成,当然,这也是为了防止一些 XSS、CSRF 攻击。目前的许多 HTML 页面都会加载来自不同域下的 CSS 样式表,图像和脚本等资源。因此,解决跨域问题显得尤为重要。
跨源资源共享标准通过新增一系列 HTTP 头,让服务器能声明那些来源可以通过浏览器访问该服务器上的资源。此时需要在 Response Header 中增加跨域相关配置,这样就可以使得资源的安全访问成为可能。
另外,对于那些可能对服务器数据产生副作用的 HTTP 请求方法(除 GET/POST/HEAD 方法),浏览器必须首先通过 OPTIONS 方法发起一个预检请求(preflight),从而获知服务端是否允许该跨域请求。服务器确认允许后,才会发起实际的 HTTP 请求。
- Access-Control-Allow-Origin:允许的域
- Access-Control-Allow-Methods:允许的跨域的请求方法
- Access-Control-Allow-Headers:在响应预检请求的时候使用,用来指明在实际的请求中,可以使用哪些自定义 HTTP 请求头
- Access-Control-Expose-Headers:设置浏览器允许访问的服务器的头信息的白名单
- Access-Control-Max-Age:这次预请求的结果的有效期是多久,单位为秒
问题描述:
如下所示,客户反馈CDN侧针对域名配置了跨域头Access-Control-Allow-Origin: *,但访问仍出现请求被跨域策略阻止。
问题分析:
从报错信息看,提示Access-Control-Allow-Origin头有多个值,但只允许一个。
从抓包的头部信息看,确实出现了2个相同的跨域头,与报错信息吻合。
1、查看域名管理>高级配置>Response Header配置,如下所示,可以发现CDN侧配置了新增头部Access-Control-Allow-Origin: *
ps:需注意配置状态是否开启,只有在开启时,底下的配置项方可生效。
2、推测应该是源站也返回了Access-Control-Allow-Origin: * 测试源站,推测得到验证。
此时原因已定位到,即源站和CDN侧均配置了跨域头,且CDN默认会缓存源站的跨域响应头。当出现2个相同的跨域头时会导致跨域功能失效。
ps:头部缓存配置文档链接https://cloud.tencent.com/document/product/228/41522
解决方案:
1、源站和CDN侧不要同时设置跨域头,建议由CDN侧设置即可。
2、CDN侧配置跨域头时,建议头部操作方式选择“设置”,而非“新增”。
“新增”模式:无论源站是否有相同的头部,仍会新增,此时就可能出现重复头部;
“设置”模式:若源站有相同的头部,且该头部CDN有缓存的情况下,会对缓存的头部进行修改,以CDN侧配置的生效。
ps:客户将源站跨域头删除后,反馈访问仍报错,这是由于访问到的仍是缓存内容,需要结合刷新操作(控制台提交或调用API接口),业务即能恢复正常。