什麼是跨域?
同源策略(Same-origin policy)
同源策略在web應用安全模型中是一個重要的概念。在這個策略下,瀏覽器允許第一個網頁中包含的指令碼可以獲取第二個網頁的資料,前提是這兩個網頁在同一個源下。
同源:需要URI、主機名、埠都相同。
這個策略可以防止一個網頁上的惡意指令碼通過DOM獲取其他網頁的敏感資料。
需要牢記的一點就是同源策略只應用於指令碼,這意味著像images、css和其他動態載入的指令碼 可以通過對應的標籤跨域訪問資源。
CORS
跨域資源共享 Cross-origin resource sharing (CORS) 是一種機制,它使用額外的 HTTP 頭來告訴瀏覽器 讓執行在一個 origin (domain) 上的Web應用被准許訪問來自不同源伺服器上的指定的資源。
CORS存在的意義
出於安全性,瀏覽器限制指令碼內發起的跨源HTTP請求。 例如,XMLHttpRequest 和 Fetch API 遵循同源策略。這意味著使用這些 API 的 Web 應用程式只能從載入應用程式的同一個域請求 HTTP 資源,除非響應報文包含了正確 CORS 響應頭。
跨源域資源共享(CORS)機制允許 Web 應用伺服器進行跨源訪問控制,從而使跨源資料傳輸得以安全進行。
瞭解了上面的內容,我們解決瀏覽器控制檯的跨域問題,一般有兩個方向:
- 後端服務設定允許跨域訪問
- 前端通過代理訪問資源
服務端
用 Node.js 的一個框架 koa 來舉例,解決跨域使用 koa-cors 非常簡單,如下:
var koa = require('koa');
var route = require('koa-route');
var cors = require('koa-cors');
var app = koa();
app.use(cors());
app.use(route.get('/', function() {
this.body = { msg: 'Hello World!' };
}));
app.listen(3000);
這個中介軟體大概做了這樣的事情:
module.exports = () => {
return async function(ctx, next) {
ctx.set('Content-Type', 'application/json');
ctx.set('Access-Control-Allow-Origin', '*');
ctx.set('Access-Control-Allow-Methods', 'GET, POST, PATCH, DELETE, PUT');
ctx.set('Access-Control-Allow-Headers', 'X-Requested-With, content-type, X-Authorization, X-uuid');
ctx.json = json.bind(ctx);
ctx.halt = halt.bind(ctx);
try {
await next();
} catch (e) {
return ctx.halt(e.code, e.message);
}
};
};
這樣前端收到的響應會是下面的樣子:
HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 00:23:53 GMT
Server: Apache/2
Access-Control-Allow-Origin: *
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: application/xml
本例中,服務端返回的 Access-Control-Allow-Origin: * 表明,該資源可以被 任意 外域訪問。
前端代理
如果使用了webpack 那麼配置一個代理就很容易,通過代理模擬出和服務端同源的請求。
//webpack.config.js
module.exports = {
//...
devServer: {
proxy: {
'/api': {
target: 'http://localhost:3000',
pathRewrite: { '^/api': '' },
},
},
},
};
這樣前端發起的請求包含/api的路徑就會被代理到 http://localhost:3000,並且會把/api替換為空。如果你的介面地址本來就包括/api,那隻要把pathRewrite: { '^/api': '' }去掉即可。
更多高階功能可參考 官網