一. 跨域問題及解決
1. 什麼是跨域訪問?
JavaScript出於安全方面的考慮,做了一個同源策略的限制,也就是說不允許跨域訪問其他資源,更通俗的說就是瀏覽器不能執行其他網站的腳本。它是由瀏覽器的同源策略造成的,是瀏覽器對JavaScript實施的安全限制。
2. 什麼是同源策略?
所謂的同源是指域名、協議、端口均爲相同。
舉例來說,http://www.yiyige.com/dir/syc.html這個網址,協議是http://,域名是www.yiyige.com,端口是80(默認端口可以省略).
3. 同源策略的作用
同源政策的目的是爲了防止惡意網站通過冒充用戶來竊取用戶的數據信息,同源策略提高了攻擊成本。
同源策略限制了以下行爲:
- Cookie、LocalStorage 和 IndexDB 無法讀取;
- DOM 和 JS 對象無法獲取;
- Ajax請求發送不出去。
4. 怎樣算是跨域訪問?
如下相對http://store.company.com/dir/page.html同源檢測的示例:
也就是說如果域名、協議、端口三者之間,如果有一個不同,則認爲不是一個網站,則會存在跨域問題。
5. 解決跨域限制的方法
- 跨域資源共享 CORS;
- 使用ajax的jsonp;
- 使用jQuery的jsonp插件;
- document.domain + iframe 跨域;
- window.name + iframe 跨域;
- location.hash + iframe 跨域;
- postMessage跨域;
- WebSocket協議跨域;
- node代理跨域;
- nginx代理跨域.
二. CORS跨域解決方案
本章節我將帶領大家,在SpringBoot項目利用CORS方案,來解決跨域方案。
1. CORS簡介
CORS是一個W3C標準,全稱是"跨域資源共享"(Cross-origin resource sharing)。
它允許瀏覽器向跨源(協議 + 域名 + 端口)服務器,發出XMLHttpRequest請求,從而克服了AJAX只能同源使用的限制。
CORS需要瀏覽器和服務器同時支持。它的通信過程,都是瀏覽器自動完成的,不需要用戶參與。
對於開發者來說,CORS通信與同源的AJAX/Fetch通信沒有差別,代碼完全一樣。
瀏覽器一旦發現請求跨源,就會自動添加一些附加的頭信息,有時還會多出一次附加的請求,但用戶不會有感覺。
因此,實現CORS通信的關鍵是服務器。只要服務器實現了CORS接口,就可以跨源通信。
2. CORS請求分類
瀏覽器將CORS請求分成兩類:
簡單請求(simple request)和非簡單請求(not-so-simple request)。
簡單請求:
瀏覽器發出CORS簡單請求,只需要在頭信息之中增加一個Origin字段。
非簡單請求:
瀏覽器發出CORS非簡單請求,會在正式通信之前,增加一次OPTIONS查詢請求,稱爲"預檢"請求(preflight)。瀏覽器先詢問服務器,當前網頁所在的域名是否在服務器的許可名單之中,以及可以使用哪些HTTP動詞和頭信息字段。只有得到肯定答覆,瀏覽器纔會發出正式的XMLHttpRequest請求,否則就報錯。
簡單請求就是HEAD、GET、POST請求,並且HTTP的頭信息不超出以下幾種字段:
Accept、Accept-Language、Content-Language、Last-Event-ID、Content-Type
注:
Content-Type只限於三個值application/x-www-form-urlencoded、multipart/form-data、text/plain
反之,就是非簡單請求。
所以實現CORS很簡單,就是在服務端加一些響應頭,並且這樣做對前端來說是無感知的,很方便。
3. 響應頭詳解:
Access-Control-Allow-Origin
該字段是必填字段。它的值要麼是請求時Origin字段的具體值,要麼是一個*,表示接受任意域名的請求。
Access-Control-Allow-Methods
該字段是必填字段。它的值是逗號分隔的一個具體的字符串或者*,表明服務器支持的所有跨域請求的方法。
注意:
返回的是所有支持的方法,而不單是瀏覽器請求的那個方法,這是爲了避免多次"預檢"請求。
Access-Control-Expose-Headers
該字段可選。CORS請求時,XMLHttpRequest對象的getResponseHeader()方法只能拿到6個基本字段:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。
如果想拿到其他字段,就必須在Access-Control-Expose-Headers裏面指定。
Access-Control-Allow-Credentials
該字段可選。它的值是一個布爾值,表示是否允許發送Cookie. 默認情況下,不發生Cookie,即:false。對服務器有特殊要求的請求,比如請求方法是PUT或DELETE,或者Content-Type字段的類型是application/json,這個值只能設爲true。如果服務器不要瀏覽器發送Cookie,刪除該字段即可。
Access-Control-Max-Age
該字段可選,用來指定本次預檢請求的有效期,單位爲秒。在有效期間,不用發出另一條預檢請求。
注意:
如果在開發中,發現每次發起請求都是兩條,一次OPTIONS,一次正常請求。注意是每次,那麼就需要配置Access-Control-Max-Age,避免每次都發出預檢請求。