zoukankan      html  css  js  c++  java
  • 跨域访问实践

    同源策略

    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.

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

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

    对于一些同源策略, 是HTML5新定义, 是否可使用,可以查询如下网站:

    http://caniuse.com/

    iframe方式嵌入页面的操作实验

    javascript的同源策略,见如下文章:

    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 

    只有在 协议 域名 和 端口 完全一致的情况下, 才认为, 两个页面对应同一个源。

    下面使用iframe和js api,构造跨域访问实例。

    js api 为 iframe.contentDocument, 父亲页面通过此js api访问iframe内嵌页面的内容,  详细见下文:

    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>
  • 相关阅读:
    PIL.Image 与 base64互转
    python pytorch ssd网络
    mysql 的左连接、又连接、内连接详细介绍
    base64图片数据类型转numpy的ndarray矩阵类型数据
    kettle学习资料
    kettle 连接 mysql8.0 报错的解决办法 org.pentaho.di.core.exception.KettleDatabaseException: Error occurred while trying to connect to the database Error connecting to database: (using class org.gjt.mm.mysql.
    python pandas 自动生成批量测试数据插入数据库 mysql
    finereport点击图表钻取到明细表包括参数传递
    finereport连接mysql8.0的解决办法
    kettle7.0 Windows10 mysql8.0 连接mysql驱动报错,问题解决
  • 原文地址:https://www.cnblogs.com/lightsong/p/3920935.html
Copyright © 2011-2022 走看看