瀏覽器默認是不允許XMLHttpRequest(ajax)發(fā)送請求到其他網站(跨域)的,
比如a網站的javascript想要從b網站獲取數據時就會被瀏覽器攔截。這也是為了安全考慮,如果不做限制的話,
a網站的js 請求b網站時默認會把b網站的cookie帶上,a網站就可以以b網站的登錄信息(b網站的cookie)去攻擊b網站。
但是實際應用中,有時候確實需要跨域請求的,跨源資源共享 (CORS)就是用來解決實現這種功能的。
CORS是http協議的一部分,需要瀏覽器和web服務器共同支持,目前絕大多數的瀏覽器和服務器都已支持。
CORS把請求分成兩類,簡單請求和非簡單請求
簡單請求:
同時滿足下面兩個條件就是簡單請求
(1) 請求方法是以下三種方法之一:
HEAD
GET
POST
(2)HTTP的頭信息不超出以下幾種字段:
Accept
Accept-Language
Content-Language
Last-Event-ID
Content-Type:只限于三個值application/x-www-form-urlencoded、multipart/form-data、text/plain

簡單請求過程如上圖,步驟為:
1.瀏覽器發(fā)現ajax的請求時跨域的,會在請求頭里面添加一個origin字段,值為當前域地址(不包含路徑)。
2.服務器拿到請求后會正常處理請求,然后再檢查請求的頭,發(fā)現origin,就知道這是跨域的請求,會檢查origin的域名是否在服務器的許可列表里,如國在就在響應頭添加一個Access-Control-Allow-Origin字段,值就是origin的值。如果不在就不設置Access-Control-Allow-Origin這個頭。然后返回相應
3.瀏覽器收到響應,知道這是個跨域的響應,檢查響應頭里是否有Access-Control-Allow-Origin,如果沒有就立即報錯并停止執(zhí)行ajax的代碼,如果有,并且值為自己的域名,或者為通配符*,就正常處理。
注意在這種簡單請求里,瀏覽器會正常發(fā)送請求的,服務器也會正常處理請求,唯一可能被攔截的就是最后瀏覽器收到響應后是否會處理,如果沒有Access-Control-Allow-Origin這個頭信息,就會停止處理。所以這個過程請求響應一定還是會被處理的。
非簡單請求
如果請求不符合簡單請求的條件,就是非簡單請求。這種請求一般會修改服務器上的資源,所以處理上比較嚴格。

非簡單請求過程如上圖,步驟為:
- 瀏覽器發(fā)現ajax的請求是跨域的,并且是非簡單請求,為了服務器的安全,不會像簡單請求一樣直接發(fā)送請求,而是會先發(fā)送一個OPTIONS的請求給服務器,詢問服務器網頁所在的域名是否在服務器的許可名單之中,以及可以使用哪些HTTP動詞和頭信息字段。只有得到肯定答復,瀏覽器才會發(fā)出正式的XMLHttpRequest請求,否則就報錯,這個請求里也會有origin頭信息。
2.服務器收到"預檢"請求以后,檢查了Origin、Access-Control-Request-Method和Access-Control-Request-Headers字段以后,確認允許跨源請求,就可以做出回應
3.瀏覽器收到服務器的“預檢請求”響應后,檢查頭信息里的Access-Control-Allow-Origin字段,如果為當前的域名或者為通配符*, 則知道這個跨域請求可以進行,就會正常發(fā)送用戶的請求,否則為不可進行,攔截用戶的請求
從上面的過程可以看到,無論是簡單還是非簡單請求,CORS的過程都需要服務端和瀏覽器共同配合,
請求只要通過了瀏覽器的驗證,服務器總是會正常處理。所以如果我們使用代碼怕蟲來發(fā)送請求,就不會有跨域請求的問題,總能成功。
另外注意到,簡單請求服務器總是會處理,攔截只發(fā)生在瀏覽器處理服務器響應過程中,在chrome的network里還是可以看到服務器返回的正常數據,并且響應碼200正常。這就警示我們,不要在簡單類型的請求里更新重要數據,否則跨站cookie攻擊漏洞就會發(fā)生。