參考:阮一峯https://www.ruanyifeng.com/blog/2016/04/cors.html
由於XHR請求只能訪問同一個域中的接口或資源,爲了實現跨域通信,一種方法就是CORS,即跨域資源共享。CORS,在服務器響應報文制定一個跨源首部(Access-Control-Allow-Oringin),就可以繞過同源限制。HTTP請求分爲簡單請求和複雜請求。
簡單請求:
需要同時滿足三個條件,1、屬於GET,POST,HEAD請求,2、請求頭只能添加Accept,Accept-language,content-type,Content-Language,Last-Event-ID,3、content-type只能取application/x-www-form-urlencoded
、multipart/form-data
、text/plain。簡單請求的流程是:
瀏覽器直接發出CORS請求,在請求頭增加一個Origin
字段,如果Origin
指定的域名在許可範圍(Access-Control-Allow-Oringin規定的)內,服務器返回的響應,會多出幾個頭信息字段。
Access-Control-Allow-Origin: * //允許訪問的域(*代表所有的)
Access-Control-Allow-Credentials: true //允許發送cookie(允許的話允許訪問的域必須明確指明哪個域)
Access-Control-Expose-Headers: Username //允許添加的頭部字段
Content-Type: text/html; charset=utf-8 //允許的content-type格式
複雜請求:
不滿足簡單請求的,如請求方法是PUT
或DELETE
,或者Content-Type
字段的類型是application/json
就是複雜請求。
客戶端發出復發請求時會受到同源策略限制,此時瀏覽器會先向服務器發送option預驗請求(preflight),請求包含了
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..
服務端就收到預驗證請求後,檢驗符合跨域的要求,就會返回返回一個響應,
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
客戶端接收到響應之後就可以正式發請求了。如果服務器不同意預檢請求,請求頭裏不會攜帶CORS相關信息,因此觸發一個錯誤,被XMLHttpRequest
對象的onerror
回調函數捕獲。控制檯會打印出如下的報錯信息
瀏覽器同源策略。
同源:如果兩個頁面的協議,端口(如果有指定)和主機都相同,則兩個頁面具有相同的源。
http://store.company.com/dir/page.html,此地址同其它地址同源檢測:
http://store.company.com/dir/inner/another.html,同源,僅路徑不同
https://store.company.com/secure.html,不同源,協議不同
http://store.company.com:81/dir/etc.html,不同源,端口不同
http://news.company.com/dir/other.html,不同源,域名不同
同源策略:同源策略控制了不同源之間的交互,例如在使用XMLHttpRequest
或 <img>
標籤時則會受到同源策略的約束。
COFS跨域資源共享:使用額外的 HTTP 頭來告訴瀏覽器 讓運行在一個 origin (domain) 上的Web應用被准許訪問來自不同源服務器上的指定的資源。當一個資源從與該資源本身所在的服務器不同的域、協議或端口請求一個資源時,資源會發起一個跨域 HTTP 請求。安全原因,瀏覽器限制從腳本內發起的跨源HTTP請求或者跨站請求可以正常發起,但是返回結果被瀏覽器攔截了。
跨域資源共享標準新增了一組 HTTP 首部字段,允許服務器聲明哪些源站通過瀏覽器有權限訪問哪些資源。另外,規範要求,對那些可能對服務器數據產生副作用的 HTTP 請求方法(特別是 GET
以外的 HTTP 請求,或者搭配某些 MIME 類型的 POST
請求),瀏覽器必須首先使用 OPTIONS
方法發起一個預檢請求(preflight request),從而獲知服務端是否允許該跨域請求。服務器確認允許之後,才發起實際的 HTTP 請求。
2.Vue2.0跨域訪問的一些操作
1.修改config路徑下的index.js文件
dev: {
env: require('./dev.env'),
assetsSubDirectory: 'static',
assetsPublicPath: '/',
proxyTable: {
'/api': {
target: 'http://xxx.com', //要請求的跨域地址
changeOrigin: true, //開啓跨域
pathRewrite: {
'^/api': ''
//重命名/api相當於http://xxx.com,設置之後/login相當
//於http://xxx.com/login,
}
}
},
host: 'localhost',
port: 8080, // 本地
autoOpenBrowser: false,
errorOverlay: true,
notifyOnErrors: true,
poll: false,
2.request.js文件
const service =axios.create({
baseURL: 'http://xxx.com', //要請求的跨域地址
timeout: 1000,
});
3.api.js,此處應該注意返回data的格式,不然會出錯
export function Login() {
service.request({
method: "post",
url: '/login',
Username: '', //可以在這裏添加自定義的字段,需要後端允許。
data: {}
})
}