
一、跨域是什么
跨域本質是瀏覽器基於同源策略的一種安全手段
同源策略(Sameoriginpolicy),是一種約定,它是瀏覽器最核心也最基本的安全功能
所謂同源(即指在同一個域)具有以下三個相同點
- 協議相同(protocol)
- 主機相同(host)
- 端口相同(port)
反之非同源請求,也就是協議、端口、主機其中一項不相同的時候,這時候就會產生跨域
一定要注意跨域是瀏覽器的限制,你用抓包工具抓取接口數據,是可以看到接口已經把數據返回回來了,只是瀏覽器的限制,你獲取不到數據。用postman請求接口能夠請求到數據。這些再次印證了跨域是瀏覽器的限制。
二、如何解決
解決跨域的方法有很多,下面列舉了三種:
- JSONP
- CORS
- Proxy
而在vue項目中,我們主要針對CORS或Proxy這兩種方案進行展開
CORS
CORS (Cross-Origin Resource Sharing,跨域資源共享)是一個系統,它由一系列傳輸的HTTP頭組成,這些HTTP頭決定瀏覽器是否阻止前端 JavaScript 代碼獲取跨域請求的響應
CORS 實現起來非常方便,只需要增加一些 HTTP 頭,讓服務器能聲明允許的訪問來源
只要后端實現了 CORS,就實現了跨域

以koa框架舉例
添加中間件,直接設置Access-Control-Allow-Origin請求頭
app.use(async (ctx, next)=> {
ctx.set('Access-Control-Allow-Origin', '*');
ctx.set('Access-Control-Allow-Headers', 'Content-Type, Content-Length, Authorization, Accept, X-Requested-With , yourHeaderFeild');
ctx.set('Access-Control-Allow-Methods', 'PUT, POST, GET, DELETE, OPTIONS');
if (ctx.method == 'OPTIONS') {
ctx.body = 200;
} else {
await next();
}
})
ps: Access-Control-Allow-Origin 設置為*其實意義不大,可以說是形同虛設,實際應用中,上線前我們會將Access-Control-Allow-Origin 值設為我們目標host
Proxy
代理(Proxy)也稱網絡代理,是一種特殊的網絡服務,允許一個(一般為客戶端)通過這個服務與另一個網絡終端(一般為服務器)進行非直接的連接。一些網關、路由器等網絡設備具備網絡代理功能。一般認為代理服務有利於保障網絡終端的隱私或安全,防止攻擊
方案一
如果是通過vue-cli腳手架工具搭建項目,我們可以通過webpack為我們起一個本地服務器作為請求的代理對象
通過該服務器轉發請求至目標服務器,得到結果再轉發給前端,但是最終發布上線時如果web應用和接口服務器不在一起仍會跨域
在vue.config.js文件,新增以下代碼
amodule.exports = {
devServer: {
host: '127.0.0.1',
port: 8084,
open: true,// vue項目啟動時自動打開瀏覽器
proxy: {
'/api': { // '/api'是代理標識,用於告訴node,url前面是/api的就是使用代理的
target: "http://xxx.xxx.xx.xx:8080", //目標地址,一般是指后台服務器地址
changeOrigin: true, //是否跨域
pathRewrite: { // pathRewrite 的作用是把實際Request Url中的'/api'用""代替
'^/api': ""
}
}
}
}
}
通過axios發送請求中,配置請求的根路徑
axios.defaults.baseURL = '/api'
方案二
此外,還可通過服務端實現代理請求轉發
以express框架為例
var express = require('express');
const proxy = require('http-proxy-middleware')
const app = express()
app.use(express.static(__dirname + '/'))
app.use('/api', proxy({ target: 'http://localhost:4000', changeOrigin: false
}));
module.exports = app
方案三
通過配置nginx實現代理
server {
listen 80;
# server_name xxx.xxx.com;
location / {
root /var/www/html;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}
location /api {
proxy_pass http://127.0.0.1:3000;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
