zoukankan      html  css  js  c++  java
  • Js跨域操作

    (二)完全不同域的跨域技术。

    如果顶级域名都不相同,例如example1.com和example2.com之间想通过JavaScript在前端通信,则所需要的技术更复杂些。

    在讲解不同域的跨域技术之前,我们首先明确一点,下面要讲的技术也同样适用于前面跨不同子域的情况,因为跨不同子域只是跨域问题的一个特例。当然,在恰当的情况下使用恰当的技术,能够保证更优的效率和更高的稳定性。

    简言之,根据不同的跨域需求,跨域技术可以归为下面几类:

    1. JSONP跨域GET请求
    2. 通过iframe实现跨域
    3. flash跨域HTTP请求
    4. window.postMessage

    下面详细介绍各种技术。

    1. JSONP。

    利用在页面中创建<script>节点的方法向不同域提交HTTP请求的方法称为JSONP,这项技术可以解决跨域提交Ajax请求的问题。JSONP的工作原理如下所述:

    假设在http://example1.com/index.php这个页面中向http://example2.com/getinfo.php 提交GET请求,我们可以将下面的JavaScript代码放在http://example1.com/index.php这个页面中来实现:

    Js代码
    1. var  eleScript= document.createElement( "script" );  
    2.   
    3. eleScript.type = "text/javascript" ;  
    4.   
    5. eleScript.src = "http://example2.com/getinfo.php" ;  
    6.   
    7. document.getElementsByTagName("HEAD" )[0].appendChild(eleScript);  
    1. var eleScript= document.createElement("script");  
    2.   
    3. eleScript.type = "text/javascript";  
    4.   
    5. eleScript.src = "http://example2.com/getinfo.php";  
    6.   
    7. document.getElementsByTagName("HEAD")[0].appendChild(eleScript);  
    var eleScript= document.createElement("script");
    
    eleScript.type = "text/javascript";
    
    eleScript.src = "http://example2.com/getinfo.php";
    
    document.getElementsByTagName("HEAD")[0].appendChild(eleScript);
    

    当GET请求从http://example2.com/getinfo.php返回时,可以返回一段JavaScript代码,这段代码会自动执行,可以用来负责调用http://example1.com/index.php页面中的一个callback函数。

    JSONP的优点是:它不像XMLHttpRequest对象实现的Ajax请求那样受到同源策略的限制;它的兼容性更好,在更加古老的浏览器中都可以运行,不需要XMLHttpRequest或ActiveX的支持;并且在请求完毕后可以通过调用callback的方式回传结果。

    JSONP的缺点则是:它只支持GET请求而不支持POST等其它类型的HTTP请求;它只支持跨域HTTP请求这种情况,不能解决不同域的两个页面之间如何进行JavaScript调用的问题。

    2. 通过iframe实现跨域。

    iframe跨域的方式,功能强于JSONP,它不仅能用来跨域完成HTTP请求,还能在前端跨域实现JavaScript调用。因此,完全不同域的跨域问题,通常采用iframe的方式来解决。

    与JSONP技术通过创建<script>节点向不同的域提交GET请求的工作方式类似,我们也可以通过在 http://example1.com/index.php页面中创建指向http://example2.com/getinfo.php的 iframe节点跨域提交GET请求。然而,请求返回的结果无法回调http://example1.com/index.php页面中的 callback函数,因为受到“同源策略”的影响。

    为了解决这个问题,我们需要在example1.com下放置一个跨域文件,比如路径是http://example1.com/crossdomain.html。

    当http://example2.com/getinfo.php这个请求返回结果的时候,它大体上有两个选择。

    第一个选择是,它可以在iframe中做一个302跳转,跳转到跨域文件http://example1.com /crossdomain.html,同时将返回结果经过URL编码之后作为参数缀在跨域文件URL后面,例如http://example1.com /crossdomain.html?result=<URL-Encoding-Content>。

    另一个选择是,它可以在返回的页面中再嵌入一个iframe,指向跨域文件,同时也是将返回结果经过URL编码之后作为参数缀在跨域文件URL后面。

    在跨域文件中,包含一段JavaScript代码,这段代码完成的功能,是从URL中提取结果参数,经过一定处理后调用原来的 http://example1.com/index.php页面中的一个预先约定好的callback函数,同时将结果参数传给这个函数。http: //example1.com/index.php页面和跨域文件是在同一个域下的,因此这个函数调用可以通过。跨域文件所在iframe和原来的 http://example1.com/index.php页面的关系,在前述第一种选择下,后者是前者的父窗口,在第二种选择下,后者是前者的父窗口的父窗口。

    根据前面的叙述,有了跨域文件之后,我们就可以实现通过iframe方式在不同域之间进行JavaScript调用。这个调用过程可以完全跟 HTTP请求无关,例如有些站点可以支持动态地调整在页面中嵌入的第三方iframe的高度,这其实是通过在第三方iframe里面检测自己页面的高度变化,然后通过跨域方式的函数调用将这个变化告知父窗口来完成的。

    既然利用iframe可以实现跨域JavaScript调用,那么跨域提交POST请求等其它类型的HTTP请求就不是难事。例如我们可以跨域调用目标域的JavaScript代码在目标域下提交Ajax请求(GET/POST/etc.),然后将返回的结果再跨域传原来的域。

    使用iframe跨域,优点是功能强大,支持各种浏览器,几乎可以完成任何跨域想做的事情;缺点是实现复杂,要处理很多浏览器兼容问题,并且传输的数据不宜过大,过大了可能会超过浏览器对URL长度的限制,要考虑对数据进行分段传输等。

    3. 利用flash实现跨域HTTP请求

    据称,flash在浏览器中的普及率高达90%以上。

    flash代码和JavaScript代码之间可以互相调用,并且flash的“安全沙箱”机制与JavaScript的安全机制并不尽相同,因此,我们可以利用flash来实现跨域提交HTTP请求(支持GET/POST等)。

    例如,我们用浏览器访问http://example1.com/index.php这个页面,在这个页面中引用了http: //example2.com/flash.swf这个flash文件,然后在flash代码中向http://example3.com /webservice.php发送HTTP请求。

    这个请求能否被成功发送,取决于在example3.com的根路径下是否放置了一个crossdomain.xml以及这个 crossdomain.xml的配置如何。flash的“安全沙箱”会保证:仅当example3.com服务器在根路径下确实放置了 crossdomain.xml文件并且在这个文件中配置了允许接受来自example2.com的flash的请求时,这个请求才能真正成功。下面是一个crossdomain.xml文件内容的例子:

    Xml代码
    1. <? xml   version = "1.0" ?>   
    2.   
    3. < cross-domain-policy >   
    4.   
    5. < allow-access-from   domain = "example2.com"   />   
    6.   
    7. </ cross-domain-policy >   
    1. <?xml version="1.0"?>  
    2.   
    3. <cross-domain-policy>  
    4.   
    5. <allow-access-from domain="example2.com" />  
    6.   
    7. </cross-domain-policy>  
    <?xml version="1.0"?>
    
    <cross-domain-policy>
    
    <allow-access-from domain="example2.com" />
    
    </cross-domain-policy>
    

    4. window.postMessage

    window.postMessage是HTML标准的下一个版本HTML5 支持的一个新特性。受当前互联网技术突飞猛进的影响,浏览器跨域通信的需求越来越强烈,HTML标准终于把跨域通信考虑进去了。但目前HTML5仍然只是一个draft。

    window.postMessage是一个安全的实现直接跨域通信的方法。但是目前并不是所有浏览器都能支持,只有Firefox 3、Safari 4和IE8可以支持这个调用。

    使用它向其它窗口发送消息的调用方式大概如下:

    Js代码
    1. otherWindow.postMessage(message, targetOrigin);  
    1. otherWindow.postMessage(message, targetOrigin);  
    otherWindow.postMessage(message, targetOrigin);

    在接收的窗口,需要设置一个事件处理函数来接收发过来的消息:

    Js代码
    1. window.addEventListener( "message" , receiveMessage,  false );  
    2. function  receiveMessage(event){  
    3.  if  (event.origin!==  "http://example.org:8080" return ;}  
    1. window.addEventListener("message", receiveMessage, false);  
    2. function receiveMessage(event){  
    3.  if (event.origin!== "http://example.org:8080"return;}  
    window.addEventListener("message", receiveMessage, false);
    function receiveMessage(event){
     if (event.origin!== "http://example.org:8080") return;}

    消息包含三个属性:data、origin(携带发送窗口所在域的真实信息)和source(代表发送窗口的handle)。

    安全性考虑:使用window.postMessage,必需要使用消息的origin和source属性来验证发送者的身份,否则会造成XSS漏洞。

    window.postMessage在功能上同iframe实现的跨域功能同样强大,并且使用简单,效率更高,但缺点是它目前在浏览器兼容方面有待提高。

    总结完所有的跨域方式之后,我们要时刻铭记,虽然跨域技术能给你带来更多的功能,催生出更灵活和更加平台化的产品,但是功能的放开也总是意味着安全的风险。在实现跨域技术的每个步骤和细节,都要时刻在头脑中考虑到对安全带来的影响,避免成为XSS攻击的漏洞。

  • 相关阅读:
    INT 21H 指令说明及使用方法 (转载)
    数织等逻辑游戏网站推荐
    常见文件格式(转载)
    我有一个通信梦 我收集的通信基础的资源
    MATLAB信号处理常用函数(转载)
    来自我的Moments-实用学习资源或网站
    三角形中的等量关系 一些等式
    【公式编辑测试】三角形中线垂线角平分线长度公式
    【备忘录】麦克斯韦速率分布
    【备忘录】转动惯量张量(转载和再补充一些东西)
  • 原文地址:https://www.cnblogs.com/snowhumen/p/2609712.html
Copyright © 2011-2022 走看看