解决前端跨域的八种方案
解決跨域的八種實現方案
由于同源策略的限制,滿足同源的腳本才可以獲取資源。雖然這樣有助于保障網絡安全,但另一方面也限制了資源的使用。 那么如何實現跨域呢,以下是實現跨域的一些方法。
一、jsonp跨域
原理:script標簽引入js文件不受跨域影響。不僅如此,帶src屬性的標簽都不受同源策略的影響。
正是基于這個特性,我們通過script標簽的src屬性加載資源,數據放在src屬性指向的服務器上,使用json格式。
由于我們無法判斷script的src的加載狀態,并不知道數據有沒有獲取完成,所以事先會定義好處理函數。服務端會在數據開頭加上這個函數名,等全部加載完畢,便會調用我們事先定義好的函數,這時函數的實參傳入的就是后端返回的數據了。
示例代碼:https://github.com/mfaying/lesson/tree/master/cross-origin/jsonp 演示網址:https://mfaying.github.io/lesson/cross-origin/jsonp/index.html
index.html
Document jsonp.jscallback({“test”: 0});
訪問index.html彈窗便會顯示0
該方案的缺點是:只能實現get一種請求。
二、document.domain + iframe跨域
此方案僅限主域相同,子域不同的應用場景。
比如百度的主網頁是www.baidu.com,zhidao.baidu.com、news.baidu.com等網站是www.baidu.com這個主域下的子域。
實現原理:兩個頁面都通過js設置document.domain為基礎主域,就實現了同域,就可以互相操作資源了。 示例代碼:https://github.com/mfaying/lesson/tree/master/cross-origin/document-domain 演示網址:https://mfaying.github.io/lesson/cross-origin/document-domain/index.html
index.html
Document child.html Document 三、location.hash + iframe跨域父頁面改變iframe的src屬性,location.hash的值改變,不會刷新頁面(還是同一個頁面),在子頁面可以通過window.localtion.hash獲取值。
示例代碼:https://github.com/mfaying/lesson/tree/master/cross-origin/location-hash 演示網址:https://mfaying.github.io/lesson/cross-origin/location-hash/index.html
index.html
Document child.html Document 點擊index.html頁面彈窗便會顯示0四、window.name + iframe跨域
原理:window.name屬性在不同的頁面(甚至不同域名)加載后依舊存在,name可賦較長的值(2MB)。
在iframe非同源的頁面下設置了window的name屬性,再將iframe指向同源的頁面,此時window的name屬性值不變,從而實現了跨域獲取數據。 示例代碼:https://github.com/mfaying/lesson/tree/master/cross-origin/window-name 演示網址:https://mfaying.github.io/lesson/cross-origin/window-name/parent/index.html
./parent/index.html
Document ./parent/proxy.html 空文件,僅做代理頁面./child.html
Document 五、postMessage跨域postMessage是HTML5提出的,可以實現跨文檔消息傳輸。
用法 getMessageHTML.postMessage(data, origin); data: html5規范支持的任意基本類型或可復制的對象,但部分瀏覽器只支持字符串,所以傳參時最好用JSON.stringify()序列化。 origin: 協議+主機+端口號,也可以設置為"*",表示可以傳遞給任意窗口,如果要指定和當前窗口同源的話設置為"/"。
getMessageHTML是我們對于要接受信息頁面的引用,可以是iframe的contentWindow屬性、window.open的返回值、通過name或下標從window.frames取到的值。
示例代碼:https://github.com/mfaying/lesson/tree/master/cross-origin/postMessage 演示網址:https://mfaying.github.io/lesson/cross-origin/postMessage/index.html
index.html
Document click child.html Document 點擊index.html頁面上的按鈕,彈窗便會顯示0。六、跨域資源共享(CORS)
只要在服務端設置Access-Control-Allow-Origin就可以實現跨域請求,若是cookie請求,前后端都需要設置。 由于同源策略的限制,所讀取的cookie為跨域請求接口所在域的cookie,并非當前頁的cookie。
CORS是目前主流的跨域解決方案。
原生node.js實現
示例代碼:https://github.com/mfaying/lesson/tree/master/cross-origin/cors 演示網址:https://mfaying.github.io/lesson/cross-origin/cors/index.html(訪問前需要先執行node server.js命令啟動本地服務器)
index.html
Document server.jsvar http = require(‘http’);
var server = http.createServer();
server.on(‘request’, function(req, res) {
res.writeHead(200, {
‘Access-Control-Allow-Credentials’: ‘true’, // 后端允許發送Cookie
‘Access-Control-Allow-Origin’: ‘https://mfaying.github.io’, // 允許訪問的域(協議+域名+端口)
‘Set-Cookie’: ‘key=1;Path=/;Domain=mfaying.github.io;HttpOnly’ // HttpOnly:腳本無法讀取cookie
});
res.write(JSON.stringify(req.method));
res.end();
});
server.listen(‘8080’);
console.log(‘Server is running at port 8080…’);
koa結合koa2-cors中間件實現
示例代碼:https://github.com/mfaying/lesson/tree/master/cross-origin/koa-cors 演示網址:https://mfaying.github.io/lesson/cross-origin/koa-cors/index.html (訪問前需要先執行node server.js命令啟動本地服務器)
index.html
Document server.jsvar koa = require(‘koa’);
var router = require(‘koa-router’)();
const cors = require(‘koa2-cors’);
var app = new koa();
app.use(cors({
origin: function (ctx) {
if (ctx.url === ‘/test’) {
return false;
}
return ‘*’;
},
exposeHeaders: [‘WWW-Authenticate’, ‘Server-Authorization’],
maxAge: 5,
credentials: true,
allowMethods: [‘GET’, ‘POST’, ‘DELETE’],
allowHeaders: [‘Content-Type’, ‘Authorization’, ‘Accept’],
}))
router.get(’/’, async function (ctx) {
ctx.body = “0”;
});
app
.use(router.routes())
.use(router.allowedMethods());
app.listen(3000);
console.log(‘server is listening in port 3000’);
七、WebSocket協議跨域
WebSocket協議是HTML5的新協議。能夠實現瀏覽器與服務器全雙工通信,同時允許跨域,是服務端推送技術的一種很好的實現。
示例代碼:https://github.com/mfaying/lesson/tree/master/cross-origin/websocket 演示網址:https://mfaying.github.io/lesson/cross-origin/websocket/index.html(訪問前需要先安裝依賴包,再執行node server.js命令啟動本地websocket服務端)
前端代碼:
Document server.jsvar WebSocketServer = require(‘websocket’).server;
var http = require(‘http’);
var server = http.createServer(function(request, response) {
response.writeHead(404);
response.end();
});
server.listen(8080, function() {
console.log(‘Server is listening on port 8080’);
});
wsServer = new WebSocketServer({
httpServer: server,
autoAcceptConnections: false
});
function originIsAllowed(origin) {
return true;
}
wsServer.on(‘request’, function(request) {
if (!originIsAllowed(request.origin)) {
request.reject();
console.log(‘Connection from origin ’ + request.origin + ’ rejected.’);
return;
}
});
八、nginx代理跨域
原理:同源策略是瀏覽器的安全策略,不是HTTP協議的一部分。服務器端調用HTTP接口只是使用HTTP協議,不存在跨越問題。
實現:通過nginx配置代理服務器(域名與test1相同,端口不同)做跳板機,反向代理訪問test2接口,且可以修改cookie中test信息,方便當前域cookie寫入,實現跨域登錄。
nginx具體配置:
#proxy服務器
server {
listen 81;
server_name www.test1.com;
}
總結
以上是生活随笔為你收集整理的解决前端跨域的八种方案的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 动态链接库 仅有.dll文件时候的使用方
- 下一篇: boost helloworlld