跨域訪問實踐

 

同源策略

An origin is defined by the scheme, host, and port of a URL. Generally speaking, documents retrieved from distinct origins are isolated from each other.javascript

https://developer.mozilla.org/zh-CN/docs/Same-origin_policy_for_file:_URIsphp

http://www.w3.org/Security/wiki/Same_Origin_Policyhtml

 

對於一些同源策略, 是HTML5新定義, 是否可以使用,能夠查詢以下網站:html5

http://caniuse.com/java

 

iframe方式嵌入頁面的操做實驗

javascript的同源策略,見以下文章:nginx

https://developer.mozilla.org/zh-CN/docs/Web/Security/Same-origin_policy?redirectlocale=zh-CN&redirectslug=JavaScript%E7%9A%84%E5%90%8C%E6%BA%90%E7%AD%96%E7%95%A5 git

只有在 協議 域名 和 端口 徹底一致的狀況下, 才認爲, 兩個頁面對應同一個源。github

 

下面使用iframe和js api,構造跨域訪問實例。web

js api 爲 iframe.contentDocument, 父親頁面經過此js api訪問iframe內嵌頁面的內容,  詳細見下文:ajax

https://developer.mozilla.org/en-US/docs/Web/API/HTMLIFrameElement

 

父親頁面爲: a.html, 內嵌一個 iframe, 引用b.html(域名爲 localhost)

父親頁面加載後, 訪問內嵌頁面的 ID爲binput 輸入框的值。

<html>
<body>
<h1>
hi, this is a.html, frame below show b.html
</h1>
<iframe src="http://localhost/b.html"></iframe>
<script type="text/javascript">
        window.onload = function(){
                console.log("a.html loaded");
                var frame = document.getElementsByTagName("iframe");
                console.log("frame src="+frame[0].src);
                var binput = frame[0].contentDocument.getElementById("binput");
                console.log("b.html binput value="+binput.value);
        }

</script>
</body>
</html>
 
內嵌頁面:b.html
其中有 binput 輸入框。
<html>
<body>
<h1>
hi, this is b.html. this page call by localhost domain.
</h1>
<input id="binput" value="binput"/>
</body>
</html>

 

實驗結果:

使用http://localhost/a.html訪問, 查看控制檯, 能夠發現 a能夠訪問b的binput。

使用http://127.0.0.1/a.html訪問, 查看控制檯, 能夠發現瀏覽器有報錯, (b.html使用localhost域名訪問),chrome瀏覽器訪問報錯以下:

 a.html loaded a.html:9
frame src=http://localhost/b.html a.html:11
Uncaught SecurityError: Failed to read the 'contentDocument' property from 'HTMLIFrameElement': Blocked a frame with origin "http://127.0.0.1" from accessing a frame with origin "http://localhost". Protocols, domains, and ports must match. a.html:12

 

CORS實踐

ajax不能跨域訪問, 同iframe跨域訪問相同, 都是受同源策略影響。

CORS 爲ajax跨域訪問的一種解決方案,詳細見下文:

 http://www.cnblogs.com/Darren_code/p/cors.html

CORS W3C規範:

http://www.w3.org/TR/cors/

 

網上介紹的例子, 可見 ajax 請求跨域,是現到達服務器,而後根據響應來決定是否在客戶端顯示響應的。

http://blog.csdn.net/hfahe/article/details/7730944

 

服務器: index.php 

添加跨域可訪問的 header 頭,能夠任何網站訪問:

<?php
 header("Access-Control-Allow-Origin:*");
 
 echo "hello ".$_SERVER['HTTP_HOST'];

 exit;
?>
Something is wrong with the XAMPP installation :-(

 

客戶端: index.html

其中的ajax使用127.0.0.1域名訪問index.php

<html>
<head> 
        <style>

        </style>
        
</head> 
<body>
        <h1>hello world!</h1>
         <input type="text" value="test"/>
         <input type="button" value="button"/>
<script type='text/javascript'> 
    function createCORSRequest(method, url) {
      var xhr = new XMLHttpRequest();
      if ("withCredentials" in xhr) {
        // 此時即支持CORS的狀況
        // 檢查XMLHttpRequest對象是否有「withCredentials」屬性
        // 「withCredentials」僅存在於XMLHTTPRequest2對象裏
        xhr.open(method, url, true);
     
      } else if (typeof XDomainRequest != "undefined") {
     
        // 不然檢查是否支持XDomainRequest,IE8和IE9支持
        // XDomainRequest僅存在於IE中,是IE用於支持CORS請求的方式
        xhr = new XDomainRequest();
        xhr.open(method, url);
     
      } else {
     
        // 不然,瀏覽器不支持CORS
        xhr = null;
     
      }
      return xhr;
    }
     
    var xhr = createCORSRequest('GET', "http://127.0.0.1/index.php");
    if (!xhr) {
      throw new Error('CORS not supported');
    }
    
    xhr.onreadystatechange = function processRequest()
    {
        if (xhr.readyState == 4) // 判斷對象狀態
        {
           if (xhr.status == 200)  // 請求結果已經成功返回
           {
              alert(xhr.responseText);
           }
        }
    };
    xhr.send();
</script>
</body>
</html>

 

 若是頁面使用 http://127.0.0.1/index.html訪問, ajax屬於站內訪問,能夠執行成功,

若是頁面使用 http://localhost/index.html訪問, ajax屬於跨站訪問,執行報錯:

XMLHttpRequest cannot load  http://127.0.0.1/index.php. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin ' http://localhost' is therefore not allowed access.  

  

nginx配置跨域

http://enable-cors.org/server_nginx.html
https://gist.github.com/michiel/1064640
 
其餘Server配置跨域

 

安全的跨源文檔通訊(Cross Document Messaging)

postMessage

https://developer.mozilla.org/zh-CN/docs/Web/API/window.postMessage

http://www.ibm.com/developerworks/cn/web/1301_jiangjj_html5message/index.html

示例來源用途第二個網址:

 服務器localhost/a.php使用postMessage傳送 消息到 內嵌的不一樣域頁面 127.0.0.1/b.php:

 <html> 
 <head> 
 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> 
 <title>Test Cross-domain communication using HTML5</title> 
 <script type="text/JavaScript"> 
     function sendIt(){ 
         // 經過 postMessage 向子窗口發送數據
         document.getElementById("otherPage").contentWindow 
             .postMessage( 
                 document.getElementById("message").value, 
                "http://127.0.0.1/"
             ); 
     } 
 </script> 
 </head> 
 <body> 
     <!-- 經過 iframe 嵌入子頁面 --> 
     <iframe src="http://127.0.0.1/b.php" 
                 id="otherPage"></iframe> 
     <br/><br/> 
     <input type="text" id="message"><input type="button" 
             value="Send to child.com" onclick="sendIt()" /> 
 </body> 
 </html>

 

b.php

<html> 
 <head> 
 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> 
 <title>Web page from child.com</title> 
 <script type="text/JavaScript"> 
     //event 參數中有 data 屬性,就是父窗口發送過來的數據
     window.addEventListener("message", function( event ) { 
         // 把父窗口發送過來的數據顯示在子窗口中
       document.getElementById("content").innerHTML+=event.data+"<br/>"; 
     }, false ); 

 </script> 
 </head> 
 <body> 
     Web page from http://127.0.0.1 
     <div id="content"></div> 
 </body> 
 </html>

 

 

阻止頁面被iframe內嵌

使用報文頭標識 : X-Frame-Options

https://developer.mozilla.org/en-US/docs/Web/HTTP/X-Frame-Options

 

詳細解釋見下面說明:

Using X-Frame-Options

There are three possible values for X-Frame-Options:

DENY
The page cannot be displayed in a frame, regardless of the site attempting to do so.
SAMEORIGIN
The page can only be displayed in a frame on the same origin as the page itself.
ALLOW-FROM uri
The page can only be displayed in a frame on the specified origin.

 

a.php 內嵌 b.php , 使用locahost引用:

<html>
<body>
<h1>
hi, this is a.php, frame below show b.php using domain localhost
</h1>
<iframe src="http://localhost/b.php"></iframe>
</body>
</html>

b.php, 經過頭decalare內嵌權限:

<?php
//header("X-Frame-Options: DENY"); // 無論地址欄訪問 localhost/a.php 仍是 127.0.0.1/a.php,都不能顯示b.php
//header("X-Frame-Options: SAMEORIGIN"); // 只有使用 localhost/a.php,才能能顯示b.php
header("X-Frame-Options: ALLOW-FROM 127.0.0.1"); // 即便使用 127.0.0.1/a.php,也能顯示b.php
?>

<html>
<body>
<h1>
hi, this is b.html. this page call by localhost domain.
</h1>
<input id="binput" value="binput"/>
</body>
</html>
相關文章
相關標籤/搜索