現在的web項目,很多都是前后端分離,特別容易出現跨域問題
那么什么是跨域問題呢?本篇文章帶你徹底從本質上弄明白什么是跨域問題以及如何解決
一 跨域有什么現象?
我們先看一下現象,如何出現跨域問題,如下實驗
- 前端:瀏覽器正在訪問一個頁面:https://www.helloworld.NET/special , 此頁面中發送了一個后端的一個 http 接口
- 后端:訪問的后端接口為: https://tiger-api.helloworld.net/v1/special/getSpecialList
上面的提示:has been blocked by CORS policy: Response to preflight request does not pass access control check
翻譯過來就是:已被CORS策略阻止:對請求的響應未通過訪問控制檢查
這就是沒有配置相關的跨域參數,是不能訪問這個接口的
二 什么是跨域問題?
舉例來說,就是:瀏覽器訪問一個 頁面時,比如訪問
https://www.helloworld.net/special
此時的 協議,主機,端口,分別是 https , www.helloworld.net , 80
那么這個頁面中,發的接口請求,這個接口的協議,主機,端口 必須和當前的頁面的一樣,三個都一樣才行,才可以訪問
否則就會出現上面的跨域現象
比如瀏覽器打開頁面
https://www.helloworld.net/special ,
在此頁面中,可以請求接口
https://www.helloworld.net/getSpecialList
因為他們的協議,主機,端口,都是相同的,是可以請求成功的。
總結一句話:在瀏覽器中,只有 協議,主機,端口三者都相同時,才可以互相訪問,否則,不可以訪問
注意:是在瀏覽器中
三 跨域問題是怎么造成的?
這個問題就涉及到了瀏覽器的 同源策略
這就是瀏覽器的同源策略,通過上面的例子可以知道
所謂的同源策略,其實就是 協議,主機, 端口都相同的,才可以互相訪問
否則只要有一個不同,是不能訪問的。
注:跨域問題,只是出現在瀏覽器中,因為瀏覽器有同源策略,所以才會有跨域問題
之前我也一直以為,跨域問題是由于瀏覽器的同源策略產生的,那么是不是只需要在請求前,加點配置就能解決了
為什么都是后端在響應頭里面加點配置才解決的?為什么是后端?跨域問題是瀏覽器造成的,這和后端有什么關系?
從上面,我們知道一個事實:我們訪問的url,如果不是同源的,也就是協議 ,主機,端口,有一個不一樣,是不能請求通的
那么問題來了:
- 為什么請求不通?
- 既然請求不通,到底是作用在http的哪個階段導致的請求不通?
- 是瀏覽器攔截了請求,沒有讓請求發出去,導致的不通?
- 還是瀏覽器攔截了響應,導致的不通?
答案就是:請求是能正常的發出去的,后端也正常的響應了,瀏覽器是把響應給攔截了,所以會出現開頭的
has been blocked by CORS policy: Response to preflight request does not pass access control check
用一張圖說明,就很容易明白了,如下圖:
四 如何解決跨域問題
通過上面的圖我們知道了,瀏覽器是攔截了響應(和第一階段的請求是沒有關系的),導致整個http請求沒有走通
那么,如何解決,讓接口能正常的發出去,正常的收到響應數據呢?
很容易就想到,如何在響應頭中添加一些特殊的字段,瀏覽器一看到有這些字段,就不攔截了,那么跨域問題不就解決了嗎
事實上正是這樣的,這也是之前好奇,解決跨域問題,為什么是后端加一些配置,其實就是在響應頭中添加了一些特殊的響應頭
那么這些特殊的響應頭是什么呢?
我們先看看 www.helloworld.net 是怎么解決的,添加了哪些響應頭字段
是的,只要后端在響應的時候,在響應頭中添加以下字段,就可以解決跨域問題
- access-control-allow-origin : 該字段是必須的。它的值要么是請求時Origin字段的值,要么是一個*,表示接受任意域名的請求。
- access-control-allow-credentials : 該字段可選。它的值是一個布爾值,表示是否允許發送Cookie。默認情況下,Cookie不包括在CORS請求之中。設為true,即表示服務器明確許可,Cookie可以包含在請求中,一起發給服務器。這個值也只能設為true,如果服務器不要瀏覽器發送Cookie,刪除該字段即可
- Access-Control-Allow-Methods : 該字段必需,它的值是逗號分隔的一個字符串,表明服務器支持的所有跨域請求的方法。注意,返回的是所有支持的方法,而不單是瀏覽器請求的那個方法。這是為了避免多次"預檢"請求。
其實最重要的就是
access-control-allow-origin 字段,添加一個 * ,允許所有的域都能訪問
當然,解決跨域還有其它方法,本文只講最常用的,其它的方法可以自己搜一下
五 總結:
通過以上的講解,現在總結如下
- 同源策略:協議,主機,端口 三者都相同,就是同一個源,只要有一個不同,就是不同的源,只有同一個源的資源才能互相訪問
- 跨域問題就是瀏覽器的同源策略造成的
- 跨域問題的本質 ,就是瀏覽器攔截了響應,所以后端只需要在響應頭中添加相應的字段,就可以解決跨域問題
還有記住下面這張圖