CORS了解与VUE跨域解决
1、CORS了解
CORS通信得關(guān)鍵地方就是服務(wù)器,只要服務(wù)器實(shí)現(xiàn)了CORS接口,就可以實(shí)現(xiàn)跨域通信
瀏覽器將CORS請求分為兩大類:簡單請求、非簡單請求
簡單請求
基本介紹
同時滿足以下條件就是簡單請求
一、 請求方法是以下三種方法之一: HEAD GET POST二、HTTP的頭信息不超出以下幾種字段: Accept Accept-Language Content-Language Last-Event-ID Content-Type:只限于三個值application/x-www-form-urlencoded、multipart/form-data、text/plain其中在第一個條件中的請求方式為HEAD的時候,只請求頁面的首部
HEAD 方法是向服務(wù)器發(fā)出指定資源的請求,只不過索要的只是響應(yīng)頭,響應(yīng)體將不會被返回。這一方法可以再不必傳輸整個響應(yīng)內(nèi)容的情況下,就可以獲取包含在響應(yīng)小消息頭中的元信息。第二個條件中字段詳解:
Accept: text/html,image/apng //代表客戶端希望接受的數(shù)據(jù)類型是html或者是png圖片類型 Accept-Language: zh-CN,zh;q=0.9 //代表客戶端可以支持語言zh-CN或者zh(值得一提的是q(0~1)是優(yōu)先級權(quán)重的意思,不寫默認(rèn)為1,這里zh-CN是1,zh是0.9) Content-Language:WEB 服務(wù)器告訴瀏覽器自己響應(yīng)的對象的語言。 Content-Type: WEB 服務(wù)器告訴瀏覽器自己響應(yīng)的對象的類型。基本流程
對于簡單請求,瀏覽器直接發(fā)送CORS請求,即在頭部信息中,添加一個origin(協(xié)議 + 域名 + 端口)字段,服務(wù)器根據(jù)這個值,決定是否同意這個請求
當(dāng)Origin指定的源,不在許可范圍內(nèi),服務(wù)器會返回一個正常的HTTP回應(yīng)。瀏覽器發(fā)現(xiàn),這個回應(yīng)的頭信息沒有包含Access-Control-Allow-Origin字段(詳見下文),就知道出錯了,從而拋出一個錯誤,被XMLHttpRequest的onerror回調(diào)函數(shù)捕獲。注意,這種錯誤無法通過狀態(tài)碼識別,因?yàn)镠TTP回應(yīng)的狀態(tài)碼有可能是200。
也就是說如果允許請求,服務(wù)器返回的響應(yīng)體會包含Access-Control-Allow-Origin字段,反之瀏覽器:攜帶origin發(fā)送給服務(wù)器
服務(wù)器:判斷origin指定源是否在許可范圍內(nèi)
Access-Control-相關(guān)字段
Access-Control-Allow-Origin: Access-Control-Allow-Credentials: Access-Control-Expose-Headers: Content-Type:1、Access-Control-Allow-Origin
該字段是必須的。它的值要么是請求時Origin字段的值,要么是一個*,表示接受任意域名的請求。
2、Access-Control-Allow-Credentials
該字段可選。它的值是一個布爾值,表示是否允許發(fā)送Cookie。默認(rèn)情況下,Cookie不包括在CORS請求之中。設(shè)為true,即表示服務(wù)器明確許可,Cookie可以包含在請求中,一起發(fā)給服務(wù)器。這個值也只能設(shè)為true,如果服務(wù)器不要瀏覽器發(fā)送Cookie,刪除該字段即可。
3、Access-Control-Expose-Headers
該字段可選。CORS請求時,XMLHttpRequest對象的getResponseHeader()方法只能拿到6個基本字段:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。如果想拿到其他字段,就必須在Access-Control-Expose-Headers里面指定。
非簡單請求
基本介紹
簡單的說就是除去簡單請求之外的就是非簡單請求
非簡單請求是那種對服務(wù)器有特殊要求的請求,比如請求方法是PUT或DELETE,或者Content-Type字段的類型是application/json。
非簡單請求的CORS請求,會在正式通信之前,增加一次HTTP查詢請求,稱為**“預(yù)檢”**請求(preflight)。
瀏覽器先詢問服務(wù)器,當(dāng)前網(wǎng)頁所在的域名是否在服務(wù)器的許可名單之中,以及可以使用哪些HTTP動詞和頭信息字段。只有得到肯定答復(fù),瀏覽器才會發(fā)出正式的XMLHttpRequest請求,否則就報(bào)錯。
比如:
var url = 'http://api.alice.com/cors'; var xhr = new XMLHttpRequest(); xhr.open('PUT', url, true); xhr.setRequestHeader('X-Custom-Header', 'value'); xhr.send();該代碼中,HTTP請求方法是PUT,并且發(fā)送一個自定義頭部信息X-Custom-Header
發(fā)送預(yù)檢請求
瀏覽器就會發(fā)現(xiàn),這是一個非簡單請求,就會自動發(fā)送一個 預(yù)檢請求,向服務(wù)器確認(rèn)是否能這樣請求,下面是 預(yù)檢信息的HTTP頭部信息
OPTIONS /cors HTTP/1.1 Origin: http://api.bob.com Access-Control-Request-Method: PUT Access-Control-Request-Headers: X-Custom-Header Host: api.alice.com Accept-Language: en-US Connection: keep-alive User-Agent: Mozilla/5.0...預(yù)檢請求用的方法是OPTIONS,表示這個請求是來詢問的,其中Origin,表示來自那個請求源
1、Access-Control-Request-Method
該字段是必須的,用來列出瀏覽器的CORS請求會用到哪些HTTP方法,上例是PUT。
2、Access-Control-Request-Headers
該字段是一個逗號分隔的字符串,指定瀏覽器CORS請求會額外發(fā)送的頭信息字段,上例是X-Custom-Header。
注意:預(yù)檢請求是瀏覽器發(fā)送給服務(wù)器時候的操作,這些信息也就是在請求體中的
預(yù)檢請求回應(yīng)
服務(wù)器在收到預(yù)檢請求后,對Origin、Access-Control-Request-Method和Access-Control-Request-Headers字段以后,確認(rèn)允許跨源請求,就可以做出回應(yīng)。
HTTP/1.1 200 OK Date: Mon, 01 Dec 2008 01:15:39 GMT Server: Apache/2.0.61 (Unix) Access-Control-Allow-Origin: http://api.bob.com Access-Control-Allow-Methods: GET, POST, PUT Access-Control-Allow-Headers: X-Custom-Header Content-Type: text/html; charset=utf-8 Content-Encoding: gzip Content-Length: 0 Keep-Alive: timeout=2, max=100 Connection: Keep-Alive Content-Type: text/plain上面就是HTTP響應(yīng)體中的內(nèi)容,關(guān)鍵的是Access-Control-Allow-Origin字段,表示http://api.bob.com可以請求數(shù)據(jù)。該字段也可以設(shè)為星號,表示同意任意跨源請求。
Access-Control-Allow-Origin: *如果服務(wù)器否定了"預(yù)檢"請求,會返回一個正常的HTTP回應(yīng),但是沒有任何CORS相關(guān)的頭信息字段。這時,瀏覽器就會認(rèn)定,服務(wù)器不同意預(yù)檢請求,因此觸發(fā)一個錯誤,被XMLHttpRequest對象的onerror回調(diào)函數(shù)捕獲。控制臺會打印出如下的報(bào)錯信息。
XMLHttpRequest cannot load http://api.alice.com. Origin http://api.bob.com is not allowed by Access-Control-Allow-Origin.服務(wù)器回應(yīng)的其他CORS相關(guān)字段如下。
Access-Control-Allow-Methods: GET, POST, PUT Access-Control-Allow-Headers: X-Custom-Header Access-Control-Allow-Credentials: true Access-Control-Max-Age: 17280001、Access-Control-Allow-Methods
該字段必需,它的值是逗號分隔的一個字符串,表明服務(wù)器支持的所有跨域請求的方法。注意,返回的是所有支持的方法,而不單是瀏覽器請求的那個方法。這是為了避免多次"預(yù)檢"請求。
2、Access-Control-Allow-Headers
如果瀏覽器請求包括Access-Control-Request-Headers字段,則Access-Control-Allow-Headers字段是必需的。它也是一個逗號分隔的字符串,表明服務(wù)器支持的所有頭信息字段,不限于瀏覽器在"預(yù)檢"中請求的字段。(我對這里的理解其實(shí)就是返回了剛開始發(fā)送給服務(wù)器的自定義請求頭)
3、Access-Control-Allow-Credentials
該字段與簡單請求時的含義相同。
4、Access-Control-Max-Age
該字段可選,用來指定本次預(yù)檢請求的有效期,單位為秒。上面結(jié)果中,有效期是20天(1728000秒),即允許緩存該條回應(yīng)1728000秒(即20天),在此期間,不用發(fā)出另一條預(yù)檢請求。
注意:只有當(dāng)預(yù)檢請求通過后,瀏覽器才會發(fā)起正常的CORS請求,和簡單請求一樣,會有一個Origin頭信息字段。服務(wù)器的回應(yīng),也都會有一個Access-Control-Allow-Origin頭信息字段。
發(fā)起簡單請求
正常的CORS請求
PUT /cors HTTP/1.1 Origin: http://api.bob.com Host: api.alice.com X-Custom-Header: value Accept-Language: en-US Connection: keep-alive User-Agent: Mozilla/5.0...瀏覽器收到的響應(yīng)體:
Access-Control-Allow-Origin: http://api.bob.com Content-Type: text/html; charset=utf-8其中Access-Control-Allow-Origin字段是每次回應(yīng)都必定包含的。
withCredentials 屬性
CORS請求默認(rèn)不發(fā)送Cookie和HTTP認(rèn)證信息。如果要把Cookie發(fā)到服務(wù)器,一方面要服務(wù)器同意,指定Access-Control-Allow-Credentials字段。
Access-Control-Allow-Credentials: true在aixos中也要進(jìn)行配置
withCredentials: true, // 設(shè)置攜帶憑證需要注意的是,如果要發(fā)送Cookie,Access-Control-Allow-Origin就不能設(shè)為星號,必須指定明確的、與請求網(wǎng)頁一致的域名。同時,Cookie依然遵循同源政策,只有用服務(wù)器域名設(shè)置的Cookie才會上傳,其他域名的Cookie并不會上傳,且(跨源)原網(wǎng)頁代碼中的document.cookie也無法讀取服務(wù)器域名下的Cookie。
以上都是對CORS的簡單相關(guān)知識介紹,看完之后我自己也有疑惑,我們發(fā)送的、接收得都是請求部分、響應(yīng)部分,那代碼與請求得轉(zhuǎn)換是什么樣得呢?下面舉出簡單得列子
代碼搭配理解
這里是發(fā)送的一個POST請求
function sendData() {var request = new XMLHttpRequest(),payload = ......;request.open('POST', 'http://public-data.com/someData', true);request.setRequestHeader('X-CUSTOM-HEADER', 'custom_header_value');request.onreadystatechange = handler;request.send(payload);}在執(zhí)行了該段代碼之后(可以看出這是一個非簡單的請求,會先進(jìn)行預(yù)檢的請求發(fā)送),瀏覽器首先發(fā)出的請求將如下所示:
OPTIONS /someData/ HTTP/1.1Host: public-data.com......Origin: http://ambergarden.comAccess-Control-Request-Method: POSTAccess-Control-Request-Headers: X-CUSTOM-HEADER在服務(wù)端看到該OPTIONS請求后,其將分析該請求中的內(nèi)容并返回一個響應(yīng),以通知瀏覽器是否允許向它發(fā)送數(shù)據(jù):
HTTP/1.1 200 OKAccess-Control-Allow-Origin: http://ambergarden.comAccess-Control-Allow-Methods: POST, GET, OPTIONSAccess-Control-Allow-Headers: X-CUSTOM_HEADERAccess-Control-Max-Age: 1728000瀏覽器分析該響應(yīng)并了解到其被允許向服務(wù)端發(fā)送數(shù)據(jù)以后,其才會向服務(wù)端發(fā)送真正的POST請求:
POST /someData/ HTTP/1.1Host: public-data.comX-CUSTOM-HEADER: custom_header_value......[Payload Here]而服務(wù)端則會接收并處理該請求(也就是響應(yīng)體中數(shù)據(jù)):
HTTP/1.1 200 OK Access-Control-Allow-Origin: http://ambergarden.com Content-Type: application/xml ......[Payload Here]參考博文:
https://www.ruanyifeng.com/blog/2016/04/cors.html
https://www.cnblogs.com/loveis715/p/4592246.html
https://www.jianshu.com/p/7faaf7e4ec06?utm_campaign=hugo
2、VUE跨域問題解決
也就是在根目錄下的vue.config.js的配置文件,然后在里面配置proxy,代碼如下:
module.exports = {devServer: {proxy: {'/api': { // 這里最好有一個 /target: 'http://192.168.119.193:8080', // 后臺接口域名changeOrigin: true, // 是否允許跨域 設(shè)置為truepathRewrite: { // 重寫域名'^/api': '/'}},}} }在配置完之后我們用新的域名來代替原來的ip和端口就行了,如下
// 比如原來我們這樣訪問接口 this.$axios.get("http://192.168.119.193:8080/addUser").then ((response) => {// handle success}).catch((error) => {// handle error})// 現(xiàn)在將接口替換成這樣就行了 this.$axios.get("/api/addUser").then ((response) => {// handle success}).catch((error) => {// handle error})這種解決辦法的其他博文也都大同小異,參考博文如下
https://blog.csdn.net/weixin_45989632/article/details/115252287?utm_medium=distribute.pc_relevant.none-task-blog-2defaultbaidujs_baidulandingword~default-0.pc_relevant_antiscan&spm=1001.2101.3001.4242.1&utm_relevant_index=3
總結(jié)
以上是生活随笔為你收集整理的CORS了解与VUE跨域解决的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 数据分析师要掌握SQL到什么程度?
- 下一篇: airpods pro是按压还是触摸_苹