面試--同源以及規避同源限制的方法

weixin_33840661發表於2017-10-05

同源概述

什麼是同源

協議相同 域名相同 埠相同

同源政策的目的

同源政策的目的,是為了保證使用者資訊的安全,防止惡意的網站竊取資料。
設想這樣一種情況:A網站是一家銀行,使用者登入以後,又去瀏覽其他網站。如果其他網站可以讀取A網站的 Cookie,會發生什麼?

不同源的情況會有哪些限制

隨著網際網路的發展,"同源政策"越來越嚴格。目前,如果非同源,共有三種行為受到限制。
(1) Cookie、LocalStorage 和 IndexDB 無法讀取。
(2) DOM 無法獲得。
(3) AJAX 請求不能傳送。

如何規避上面的三種限制?

cookie

Cookie 是伺服器寫入瀏覽器的一小段資訊,只有同源的網頁才能共享。
但是,兩個網頁一級域名相同,只是二級域名不同,瀏覽器允許通過設定document.domain共享 Cookie。
舉例來說,A網頁是http://w1.example.com/a.html,B網頁是http://w2.example.com/b.html,那麼只要設定相同的document.domain,兩個網頁就可以共享Cookie。

document.domain = 'example.com';

現在,A網頁通過指令碼設定一個 Cookie。

document.cookie = "test1=hello";

B網頁就可以讀到這個 Cookie。

var allCookie = document.cookie;


開啟的新視窗和當前視窗不同源

如果兩個網頁不同源,就無法拿到對方的DOM。典型的例子是iframe視窗和window.open方法開啟的視窗,它們與父視窗無法通訊。
完全不同源的網站,目前有三種方法,可以解決跨域視窗的通訊問題。
1、片段識別符號
片段識別符號(fragment identifier)指的是,URL的#號後面的部分,比如http://example.com/x.html#fra...的#fragment。如果只是改變片段識別符號,頁面不會重新重新整理。
父視窗的

var src = originURL + '#' + data;
document.getElementById('myIFrame').src = src;

子視窗的

window.onhashchange = checkMessage;

function checkMessage() {
  var message = window.location.hash;
  // ...
}

2、window.postMessage
可以隱藏一個iframe iframe裡邊的為子頁面
子頁面傳送資訊

 var ifr=window.parent;
    var targeOrigin='http://localhost:63342/reactWork';
    ifr.postMessage("asa1111",targeOrigin);

父頁面
在父頁面中通過 隱藏一個iframe來實現跨域的資料傳輸
html

<iframe src="http://localhost:3000/talk" id="test"></iframe>

js

<script type="text/javascript">
     window.addEventListener('message',function (event) {
         console.log(event)
         if(event.origin=='http://localhost:1234'){
             console.log(event.data)  //會輸出event的資料
         }
     },false)
</script>

Ajax

同源政策規定,AJAX請求只能發給同源的網址,否則就報錯。
1、jsonp
JSONP是伺服器與客戶端跨源通訊的常用方法。最大特點就是簡單適用,老式瀏覽器全部支援,伺服器改造非常小。
基本的思想
網頁通過新增一個<script>元素,前端的瀏覽器向伺服器請求JSON資料,這種做法是不會受到同源政策的限制;伺服器在收到請求後,將資料放在一個指定名字的回撥函式foo裡傳回來。
前端的js

    //動態的插入js指令碼
    function addScriptTag(src) {       
        var script = document.createElement('script');
        script.setAttribute("type","text/javascript");
        console.log(src)
        script.src = src;
        document.body.appendChild(script);
    }
    window.onload = function () {
        addScriptTag('http://localhost:3000/talk?callback=foo');
    }
    //傳到伺服器端的那個回撥函式
    function foo(data) {
        console.log('Your public IP address is: ' + data.ip);
    };

伺服器端
直接在index.ejs中寫 給這個回撥函式傳遞的就是要傳送的資料

foo({
"ip": "8.8.8.8"
});

2、websocket 關於websocket可以檢視我的另一篇文章
3、cors 關於cors可以檢視我的另一篇文章 https://segmentfault.com/a/11...

相關文章