前端開發的童鞋,應該都有聽過跨域請求,但這其中的細節可能還不清楚,比如:
<pre>
- 什麼是跨域請求?
- 爲什麼會存在跨域請求?
- 跨域請求是怎麼工作的?
- 如何解決跨域請求?
</pre>
1. 什麼是跨域請求
跨域請求 - 訪問其他域名的資源,隨着業務的複雜化及前後端的分離,我們需要經常訪問其他域名的資源,因此這裏就涉及到跨域訪問,下圖給出了跨域訪問的例子
image
2. 爲什麼會存在跨域請求
可能有童鞋就說了,何必這麼麻煩,直接允許訪問不就行了,也許前期就是這樣,於是就出現了CSRF(跨站請求僞造),可以看下圖:
image
因此網站A就必須添加訪問限制,即決策是否允許網站B訪問
3. 跨域請求是怎麼工作的
跨域請求針對不同的請求會採用不用的策略,這裏羅列如下:
3.1 簡單模式(Simple requests)
請求方法:
GET
HEAD
POST
請求頭:
Accept
Accept-Language
Content-Language
Content-Type
Content-Type:
application/x-www-form-urlencoded
multipart/form-data
text/plain
滿足以上特徵的請求就是Simple request,採用如下工作模式:
- 瀏覽器從網站B獲取html資源
- 瀏覽器發送請求到網站A,並攜帶網站B的Origin,如Server-b.com
- 網站A檢測自身的Access-Control-Allow-Origin是否包含Origin,如果包含返回正確數據,否則返回空
image
PS: Access-Control-Allow-Origin: * 表示允許所有網站方法
3.2 預檢模式(Preflighted requests)
除了簡單請求外,其他請求訪問前需要先發一條預檢請求,比如採用OPTIONS,採用如下工作模式:
- 瀏覽器從網站B獲取html資源
- 瀏覽器發送OPTIONS請求,並攜帶如下信息
- Origin - 網站B域名
- Access-Control-Request-Method - 待請求方法,如POST
- Access-Control-Request-Headers - 待請求頭信息
- 網站A檢測自身的Origin、Access-Control-Allow-Methods、Access-Control-Allow-Headers是否包含客戶端發送的值
- 如果包含,則返回200,瀏覽器發送真正的請求(也需要攜帶CROS信息),服務器返回正確數據
- 如果不包含,則返回錯誤,並返回Origin、Access-Control-Allow-Methods、Access-Control-Allow-Headers
image
4. 常見錯誤
- 4.1 Access-Control-Allow-Origin不匹配
一般會報如下錯誤:已攔截跨源請求:同源策略禁止讀取位於 http://127.0.0.1:19110/uptoken 的遠程資源。(原因:CORS 頭 'Access-Control-Allow-Origin' 不匹配 '1')
解決方法:檢測服務端配置的Access-Control-Allow-Origin,應該包含前端所在服務的域名
- 4.2 Access-Control-Allow-Headers不匹配
一般會報如下錯誤:已攔截跨源請求:同源策略禁止讀取位於 http://127.0.0.1:19110/uptoken 的遠程資源。(原因:來自 CORS 預檢通道的 CORS 頭 'Access-Control-Allow-Headers' 的令牌 'if-modified-since' 無效)
解決方法:檢測服務端配置的Access-Control-Allow-Headers,應該包含前端發送的Access-Control-Request-Headers(可以抓包看前端發送的數據)