前幾天在幫後端排查一個cors的問題的時候發現的一些小坑特此記錄json
**後端
cors的本質是出於安全緣由,瀏覽器限制從腳本內發起的跨源HTTP請求。 例如,XMLHttpRequest和Fetch
API遵循同源策略。 這意味着使用這些API的Web應用程序只能從加載應用程序的同一個域請求HTTP資源,除非使用CORS頭文件。
跨域並不是必定是瀏覽器限制了跨站請求,也有多是跨站請求能夠正常發起,可是返回結果被瀏覽器攔截了。最好的例子是 CSRF
跨站攻擊原理,請求是發送到了後端服務器不管是否跨域!注意:有些瀏覽器不容許從 HTTPS 的域跨域訪問 HTTP,好比 Chrome 和
Firefox,這些瀏覽器在請求還未發出的時候就會攔截請求。
**api
本case場景描述以下:
用戶在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 的一個的特性是,能夠基於 HTTP cookies 和 HTTP 認證信息發送身份憑證。通常而言,對於跨域 XMLHttpRequest 或 Fetch 請求,瀏覽器不會發送身份憑證信息。若是要發送憑證信息,須要設置 XMLHttpRequest 的某個特殊標誌位。安全
var invocation = new XMLHttpRequest(); var url = 'http://bar.other/resources/credentialed-content/'; function callOtherDomain(){ if(invocation) { invocation.open('GET', url, true); invocation.withCredentials = true;//這個是重點 invocation.onreadystatechange = handler; invocation.send(); } }
將 XMLHttpRequest 的 withCredentials 標誌設置爲 true,從而向服務器發送 Cookies。服務器端的響應須要攜帶 Access-Control-Allow-Credentials: true ,瀏覽器纔會把響應內容返回給請求的發送者。服務器
另外須要注意的是
對於附帶身份憑證的請求,服務器不得設置 Access-Control-Allow-Origin 的值爲「」。 這是由於請求的首部中攜帶了 Cookie 信息,若是 Access-Control-Allow-Origin 的值爲「」,請求將會失敗。而將 Access-Control-Allow-Origin 的值設置爲 http://foo.example,則請求將成功執行。cookie
tips:
在跨域訪問時,XMLHttpRequest對象的getResponseHeader()方法只能拿到一些最基本的響應頭,Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma,若是要訪問其餘頭,則須要服務器設置本響應頭Access-Control-Expose-Headers 頭讓服務器把容許瀏覽器訪問的頭放入白名單,例如:cors
Access-Control-Expose-Headers: X-My-Custom-Header, X-Another-Custom-Header
其餘詳細信息見個人博客jsonp