一文讀懂跨域問題。 自己實測,我看的別人文章有人說這樣,有人說那樣,我就自己好好測試了一下。
如何在本機測試跨域:
這里以tomcat服務器為例。 其實很簡單,就是服務器啟動后的本機域名是localhost,但是只要在地址欄輸入127.0.0.1來訪問tomcat,這時候就已經構成跨域了。
這時候請求頭中會包含Origin字段,表示Host與Origin 不一致 這就已經是跨域了。
Host
localhost:8080
Origin
http://127.0.0.1:8080
HTTP跨域訪問控制的機制叫CORS (Cross-Origin Resource Sharing)該機制允許Web應用服務器進行跨域訪問控制,從而使跨域數據傳輸得以安全進行??缬蛸Y源共享標準新增了一組 HTTP 首部字段,允許服務器聲明哪些源站有權限訪問哪些資源。
首先在某種條件下 跨域請求資源是被允許,而不是服務端說了算,也不是說所有的跨域一開始都是被禁止的。
直接就能跨域的請求成功的,叫做簡單請求,簡單請求必須同時滿足三個條件:
- 使用 GET HEAD POST三種方法之一。
- 沒有人為設置該集合之外的其他首部字段。該集合為
Accept
Accept-Language
Content-Language
Content-Type (需要注意額外的限制)
DPR
Downlink
Save-Data
Viewport-Width
Width
3 Content-Type 必須是三者之一
application/x-www-form-urlencoded
multipart/form-data
text/plain
如果滿足以上條件的話,跨域是可以正常訪問。但這是不能攜帶cookie的。
能否攜帶cookie進行跨域的設置:
只需要客戶端設置 xhr.withCredentials = true; 服務端不用任何配置。如果進入預檢請求的話就是另一回事了,下面說。
那么以上就能夠正常跨域訪問了。
但是問題來,正常的前后端通信的消息格式并不是表單,而是json。
這時候前端需要設置
xhr.setRequestHeader("Content-type", "application/json");
這就 違背了 前面所說的 必須同時滿足三個條件。
這時候 就要進入預檢請求,預檢請求 “需預檢的請求”要求必須首先使用 OPTIONS 以獲知服務器是否允許該實際請求。"預檢請求“的使用,可以避免跨域請求對服務器的用戶數據產生未預期的影響。
預檢請求的過程是自動進行的。就是先進行一次OPTIONS 請求。如果允許了,之后才會進行實際請求。
CORS的各種訪問控制字段 ,在預檢請求的時候 才會檢查 比如"Access-Control-Allow-Origin" 等等Access-Control-Allow開頭的字段。
主要會檢查以下字段:
response.setHeader("Access-Control-Allow-Origin", "http://127.0.0.1:8080");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, DELETE, PUT");
response.setHeader("Access-Control-Allow-Headers", "x-requested-with, Content-Type");
response.setHeader("Access-Control-Allow-Credentials", "true");
如果這時候Access-Control-Allow-Origin沒有配置的話,客戶端就真的會被禁止了。當然這里也不能配置為* ,這樣也會被瀏覽器禁止,并提示憑據不支持,如果 CORS 頭 ‘Access-Control-Allow-Origin’ 為 ‘*’。
如果客戶端請求時帶有自定義的字段,那么這里也必須把該字段添加到Access-Control-Allow-Headers里面。
如果客戶端想要帶cookie進行跨域,這里也必須設置Access-Control-Allow-Credentials為true。
所以說,只要進入了預檢請求, 是否支持跨域就是服務器來決定了,就必須配置各種各樣的Access-Control-Allow字段。 而簡單請求下,這些字段是否配置是沒有半點關系的。
一般來說 預檢請求是很容易觸發的。比如剛才所說的更改Content-Type為json, 人為設置了安全字段集合之外的其他首部字段,比如有時候在復制粘貼別人代碼的時候多粘貼了一條不必要的請求頭xhr.setRequestHeader("xxx-version", "5.3.0"); 這就悲劇了, 這樣的話你的服務端必須也要配置允許這個xxx-version字段才可以。
(作者的csdn博客地址,http://blog.csdn.net/dreamytian)
(轉載請注明 出處http://www.lxweimin.com/p/ccd6fea996ef)