前几天在帮后台排查一个cors问题的时候,发现了一些小坑,特此记录下**cors的本质是出于安全考虑,浏览器限制访问脚本A内发起的跨源HTTP请求。例如,XMLHttpRequest和FetchAPI遵循同源策略。这意味着使用这些API的Web应用程序只能从加载应用程序的同一域请求HTTP资源,除非使用CORS标头。跨域并不一定意味着浏览器限制了跨站请求。也可能是可以正常发起跨站请求,但是返回的结果被浏览器拦截了。最好的例子就是CSRF跨站攻击的原理,无论是否跨域,请求都发送到后端服务器!注意:有些浏览器不允许从HTTPS域跨域访问HTTP,比如Chrome和Firefox,这些浏览器会在请求发送前拦截。**本案例场景描述如下:用户在a.com域名下跨域访问b.com域名下的api接口,使用XMLHttpRequest的跨域头请求。b.com这个域名也允许跨域Access-Control-Allow-Origin,但是奇怪的是在访问b.com的接口时,有的api可以访问成功,有的api不能访问。调查发现,访问失败的API都需要用户的登录状态。但是用户已经在b.com上登录了。将XMLHttpRequest请求换成jsonp请求可以使请求成功(这好像是废话)。..由此推测,XMLHttpRequest在添加cors头时,并没有将b.com的用户cookie信息带过来。查看MDN文档https://developer.mozilla.org...,找到答案如下:Fetch和CORS的一个特点是可以根据HTTPcookies和HTTP认证信息发送身份凭证。通常,浏览器不会为跨源XMLHttpRequest或Fetch请求发送凭据信息。如果要发送凭证信息,需要设置一个特殊的XMLHttpRequest标志。varinvocation=newXMLHttpRequest();varurl='http://bar.other/resources/credentialed-content/';functioncallOtherDomain(){if(invocation){invocation.open('GET',url,true);invocation.withCredentials=true;//这是关键点invocation.onreadystatechange=handler;调用.send();}}将XMLHttpRequest的withCredentials标志设置为true以将Cookie发送到服务器。服务器端响应需要携带Access-Control-Allow-Credentials:true,浏览器会将响应内容返回给请求的发送方。另外需要注意的是,对于带有身份凭证的请求,服务器不得将Access-Control-Allow-Origin的值设置为“”。这是因为请求的header中携带了Cookie信息,如果Access-Control-Allow-Origin的值为"",请求就会失败。相反,将Access-Control-Allow-Origin的值设置为http://foo.example,请求就会成功。tips:在跨域访问中,XMLHttpRequest对象的getResponseHeader()方法只能获取一些基本的响应头,比如Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma,如果你想的话访问其他header,服务器需要设置响应头Access-Control-Expose-Headers,让服务器把允许浏览器访问的headers放入白名单,例如:Access-Control-Expose-Headers:X-My-Custom-Header,X-Another-Custom-Header其他细节见我的博客
