CORS了解与VUE跨域解决
1、CORS了解
CORS通信得關鍵地方就是服務器,只要服務器實現了CORS接口,就可以實現跨域通信
瀏覽器將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 方法是向服務器發出指定資源的請求,只不過索要的只是響應頭,響應體將不會被返回。這一方法可以再不必傳輸整個響應內容的情況下,就可以獲取包含在響應小消息頭中的元信息。第二個條件中字段詳解:
Accept: text/html,image/apng //代表客戶端希望接受的數據類型是html或者是png圖片類型 Accept-Language: zh-CN,zh;q=0.9 //代表客戶端可以支持語言zh-CN或者zh(值得一提的是q(0~1)是優先級權重的意思,不寫默認為1,這里zh-CN是1,zh是0.9) Content-Language:WEB 服務器告訴瀏覽器自己響應的對象的語言。 Content-Type: WEB 服務器告訴瀏覽器自己響應的對象的類型。基本流程
對于簡單請求,瀏覽器直接發送CORS請求,即在頭部信息中,添加一個origin(協議 + 域名 + 端口)字段,服務器根據這個值,決定是否同意這個請求
當Origin指定的源,不在許可范圍內,服務器會返回一個正常的HTTP回應。瀏覽器發現,這個回應的頭信息沒有包含Access-Control-Allow-Origin字段(詳見下文),就知道出錯了,從而拋出一個錯誤,被XMLHttpRequest的onerror回調函數捕獲。注意,這種錯誤無法通過狀態碼識別,因為HTTP回應的狀態碼有可能是200。
也就是說如果允許請求,服務器返回的響應體會包含Access-Control-Allow-Origin字段,反之瀏覽器:攜帶origin發送給服務器
服務器:判斷origin指定源是否在許可范圍內
Access-Control-相關字段
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
該字段可選。它的值是一個布爾值,表示是否允許發送Cookie。默認情況下,Cookie不包括在CORS請求之中。設為true,即表示服務器明確許可,Cookie可以包含在請求中,一起發給服務器。這個值也只能設為true,如果服務器不要瀏覽器發送Cookie,刪除該字段即可。
3、Access-Control-Expose-Headers
該字段可選。CORS請求時,XMLHttpRequest對象的getResponseHeader()方法只能拿到6個基本字段:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。如果想拿到其他字段,就必須在Access-Control-Expose-Headers里面指定。
非簡單請求
基本介紹
簡單的說就是除去簡單請求之外的就是非簡單請求
非簡單請求是那種對服務器有特殊要求的請求,比如請求方法是PUT或DELETE,或者Content-Type字段的類型是application/json。
非簡單請求的CORS請求,會在正式通信之前,增加一次HTTP查詢請求,稱為**“預檢”**請求(preflight)。
瀏覽器先詢問服務器,當前網頁所在的域名是否在服務器的許可名單之中,以及可以使用哪些HTTP動詞和頭信息字段。只有得到肯定答復,瀏覽器才會發出正式的XMLHttpRequest請求,否則就報錯。
比如:
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,并且發送一個自定義頭部信息X-Custom-Header
發送預檢請求
瀏覽器就會發現,這是一個非簡單請求,就會自動發送一個 預檢請求,向服務器確認是否能這樣請求,下面是 預檢信息的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...預檢請求用的方法是OPTIONS,表示這個請求是來詢問的,其中Origin,表示來自那個請求源
1、Access-Control-Request-Method
該字段是必須的,用來列出瀏覽器的CORS請求會用到哪些HTTP方法,上例是PUT。
2、Access-Control-Request-Headers
該字段是一個逗號分隔的字符串,指定瀏覽器CORS請求會額外發送的頭信息字段,上例是X-Custom-Header。
注意:預檢請求是瀏覽器發送給服務器時候的操作,這些信息也就是在請求體中的
預檢請求回應
服務器在收到預檢請求后,對Origin、Access-Control-Request-Method和Access-Control-Request-Headers字段以后,確認允許跨源請求,就可以做出回應。
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響應體中的內容,關鍵的是Access-Control-Allow-Origin字段,表示http://api.bob.com可以請求數據。該字段也可以設為星號,表示同意任意跨源請求。
Access-Control-Allow-Origin: *如果服務器否定了"預檢"請求,會返回一個正常的HTTP回應,但是沒有任何CORS相關的頭信息字段。這時,瀏覽器就會認定,服務器不同意預檢請求,因此觸發一個錯誤,被XMLHttpRequest對象的onerror回調函數捕獲??刂婆_會打印出如下的報錯信息。
XMLHttpRequest cannot load http://api.alice.com. Origin http://api.bob.com is not allowed by Access-Control-Allow-Origin.服務器回應的其他CORS相關字段如下。
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
該字段必需,它的值是逗號分隔的一個字符串,表明服務器支持的所有跨域請求的方法。注意,返回的是所有支持的方法,而不單是瀏覽器請求的那個方法。這是為了避免多次"預檢"請求。
2、Access-Control-Allow-Headers
如果瀏覽器請求包括Access-Control-Request-Headers字段,則Access-Control-Allow-Headers字段是必需的。它也是一個逗號分隔的字符串,表明服務器支持的所有頭信息字段,不限于瀏覽器在"預檢"中請求的字段。(我對這里的理解其實就是返回了剛開始發送給服務器的自定義請求頭)
3、Access-Control-Allow-Credentials
該字段與簡單請求時的含義相同。
4、Access-Control-Max-Age
該字段可選,用來指定本次預檢請求的有效期,單位為秒。上面結果中,有效期是20天(1728000秒),即允許緩存該條回應1728000秒(即20天),在此期間,不用發出另一條預檢請求。
注意:只有當預檢請求通過后,瀏覽器才會發起正常的CORS請求,和簡單請求一樣,會有一個Origin頭信息字段。服務器的回應,也都會有一個Access-Control-Allow-Origin頭信息字段。
發起簡單請求
正常的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...瀏覽器收到的響應體:
Access-Control-Allow-Origin: http://api.bob.com Content-Type: text/html; charset=utf-8其中Access-Control-Allow-Origin字段是每次回應都必定包含的。
withCredentials 屬性
CORS請求默認不發送Cookie和HTTP認證信息。如果要把Cookie發到服務器,一方面要服務器同意,指定Access-Control-Allow-Credentials字段。
Access-Control-Allow-Credentials: true在aixos中也要進行配置
withCredentials: true, // 設置攜帶憑證需要注意的是,如果要發送Cookie,Access-Control-Allow-Origin就不能設為星號,必須指定明確的、與請求網頁一致的域名。同時,Cookie依然遵循同源政策,只有用服務器域名設置的Cookie才會上傳,其他域名的Cookie并不會上傳,且(跨源)原網頁代碼中的document.cookie也無法讀取服務器域名下的Cookie。
以上都是對CORS的簡單相關知識介紹,看完之后我自己也有疑惑,我們發送的、接收得都是請求部分、響應部分,那代碼與請求得轉換是什么樣得呢?下面舉出簡單得列子
代碼搭配理解
這里是發送的一個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);}在執行了該段代碼之后(可以看出這是一個非簡單的請求,會先進行預檢的請求發送),瀏覽器首先發出的請求將如下所示:
OPTIONS /someData/ HTTP/1.1Host: public-data.com......Origin: http://ambergarden.comAccess-Control-Request-Method: POSTAccess-Control-Request-Headers: X-CUSTOM-HEADER在服務端看到該OPTIONS請求后,其將分析該請求中的內容并返回一個響應,以通知瀏覽器是否允許向它發送數據:
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瀏覽器分析該響應并了解到其被允許向服務端發送數據以后,其才會向服務端發送真正的POST請求:
POST /someData/ HTTP/1.1Host: public-data.comX-CUSTOM-HEADER: custom_header_value......[Payload Here]而服務端則會接收并處理該請求(也就是響應體中數據):
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, // 是否允許跨域 設置為truepathRewrite: { // 重寫域名'^/api': '/'}},}} }在配置完之后我們用新的域名來代替原來的ip和端口就行了,如下
// 比如原來我們這樣訪問接口 this.$axios.get("http://192.168.119.193:8080/addUser").then ((response) => {// handle success}).catch((error) => {// handle error})// 現在將接口替換成這樣就行了 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
總結
以上是生活随笔為你收集整理的CORS了解与VUE跨域解决的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 数据分析师要掌握SQL到什么程度?
- 下一篇: airpods pro是按压还是触摸_苹