簡單瞭解跨域及其解決方案(一)

1. 什麼是跨域

跨域是指一個域下的文檔或腳本試圖去請求另一個域下的資源

一般指
1.) 資源跳轉: A鏈接、重定向、表單提交
2.) 資源嵌入: link、script、img、frame等dom標籤,還有樣式中background:url()、@font-face()等文件外鏈
3.) 腳本請求: js發起的ajax請求、dom和js對象的跨域操作等

我們通常所說的跨域是指的瀏覽器同源策略限制的一類請求場景。

同源策略
同源策略/SOP(Same origin policy)是一種約定,由Netscape公司1995年引入瀏覽器,它是瀏覽器最核心也最基本的安全功能,如果缺少了同源策略,瀏覽器很容易受到XSS、CSFR等攻擊。所謂同源是指"協議+域名+端口"三者相同,即便兩個不同的域名指向同一個ip地址,也非同源。

同源策略一般限制
1.) Cookie、LocalStorage 和 IndexDB 無法讀取
2.) DOM 和 Js對象無法獲得
3.) AJAX 請求不能發送

常見的跨域場景

url 說明 是否允許通信
http://www.baidu.com/1.js http://www.baidu.com/2.js 同一域名,不同文件或路徑 允許
http://www.baidu.com:8000/1.js http://www.baidu.com/2.js 同一域名,不同端口 不允許
http://www.baidu.com/1.js https://www.baidu.com/2.js 同一域名,不同協議 不允許
http://www.baidu.com/1.js http://192.168.14.52/12.js 域名和域名對應相同ip 不允許
http://www.baidu.com/1.js http://x.baidu.com/1112.js 主域相同,子域不同 不允許
http://www.baidu1.com/a.js http://www.baidu2.com/b.js 不同域名 不允許

跨域解決方案

1、 通過jsonp跨域
2、 document.domain + iframe跨域
3、 location.hash + iframe
4、 window.name + iframe跨域
5、 跨域資源共享(CORS)
6、 nginx代理跨域
7、 nodejs中間件代理跨域
8、 WebSocket協議跨域

一,通過jsonp跨域

爲了減輕web服務器的負載,我們把js、css,img等靜態資源分離到另一臺獨立域名的服務器上,在html頁面中再通過相應的標籤從不同域名下加載靜態資源,而被瀏覽器允許,基於此原理,我們可以通過動態創建script,再請求一個帶參網址實現跨域通信。

1.原生實現

<script>
    var script = document.createElement('script');
    script.type = 'text/javascript';

    // 傳參一個回調函數名給後端,方便後端返回時執行這個在前端定義的回調函數
    script.src = 'http://www.baidu.com:8081/login?user=admin&callback=handleCallback';
    document.head.appendChild(script);

    // 回調執行函數
    function handleCallback(res) {
        alert(JSON.stringify(res));
    }
 </script>

服務端返回如下(返回時即執行全局函數):

handleCallback({"status": true, "user": "admin"})

2.jquery ajax

$.ajax({
    url: 'http://www.baidu.com:8081/login',
    type: 'get',
    dataType: 'jsonp',  // 請求方式爲jsonp
    jsonpCallback: "handleCallback",    // 自定義回調函數名
    data: {}
});

3.vue

this.$http.jsonp('http://www.baidu.com:8081/login', {
    params: {},
    jsonp: 'handleCallback'
}).then((res) => {
    console.log(res); 
})

後端node.js代碼

const querystring = require('querystring');
const http = require('http');
const server = http.createServer();

server.on('request', function(req, res) {
    const params = qs.parse(req.url.split('?')[1]);
    const fn = params.callback;

    // jsonp返回設置
    res.writeHead(200, { 'Content-Type': 'text/javascript' });
    res.write(fn + '(' + JSON.stringify(params) + ')');

    res.end();
});

server.listen('8081');
console.log('Server is running at port 8081...');
jsonp缺點:只能實現get一種請求。

二、 document.domain + iframe跨域

只限於主域相同,子域不同的跨域應用場景。

實現原理:兩個頁面都通過js強制設置document.domain爲基礎主域,就實現了同域。

1.父窗口:(http://www.baidu.com/1.html)

<iframe id="iframe" src="http://child.baidu.com/2.html"></iframe>
<script>
    document.baidu = 'baidu.com';
    var user = 'admin';
</script>

2.子窗口:(http://www.baidu.com/2.html)

<script>
    document.baidu = 'baidu.com';
    // 獲取父窗口中變量
    alert('get js data from parent ---> ' + window.parent.user);
</script>

剩下跨域解決方式在 簡單瞭解跨域及其解決方案(二) 裏進行說明

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章