zoukankan      html  css  js  c++  java
  • 前端遇到的跨域问题及解决方案一

    《JavaScript 高级程序设计》一直断断续续的看这本书,有些地方看了三四遍,有些地方一遍也没有看过。这本书真心是非常不错的书,再随着google些资料,还是受益很多的。
    昨睡不着,翻了下看看跨域,今又认真搜了下,有跟先前不一样的体会了。工作中遇到的跨域,比如说iframe引用某某盛典的页面,你是没有办法设置高度的~~有嵌套iframe的方法获取高度,但是对方这个页面不是你一家用的,你不能有任何修改,它是不会内嵌什么iframe的。真心没办法解决~~ 有些东西,你是甲方的话,别家提供,基本是采用JSONP方式,约定个函数传递数据,或者是直接链别家的JS文件有全局对象。

    让我们从书开始吧~

    Ajax跨域请求问题

    Ajax是无需刷新页面就能够从服务器去的数据的一种方法。负责Ajax运作的核心对象是XMLHttpRequest(XHR)对象。同源策略是对XHR的一个主要约束,它为通信设置了“相同的域、相同的端口、相同的协议”这一限制。试图访问上述限制之外的资源都会引发安全错误,除非采用被认可的跨域解决方案。这个方案叫做CORS(Cross-Origin Resource Sharing ,跨源资源共享。)提一句,对于未被授权系统有权访问某个资源的情况,称之为CSRF(Cross-Site Request Forgery, 跨站点请求伪造)。

    CORS

    CORS背后的基本思想,是用用自定义的HTTP头部让浏览器与服务器进行沟通,从而决定请求或响应是应该成功还是失败。

    比如一个简单的使用GET或POST发送的请求,它没有自定义的头部,而主体内容是text/plain。在发送该请求时,需要给它附加一个额外的Origin头部,其中包含请求页面的源信息(协议、域名、端口),以便服务器根据这个头部信息来决定是否给予响应。示例

    Origin: http://www.cnblogs.com/

    如果服务器认为这个请求可以接受,就在Access-Control-Allow-Origin头部中回发相同的源信息(如果过是公共资源,可以回发”*”)。

    Access-Control-Allow-Origin:http://www.cnblogs.com/

    如果没有这个头部,或这个有这个头部但源信息不匹配,浏览器就会驳回请求。正常情况下,浏览器会处理请求。注意,请求和响应中都不包含cookie信息。

    IE对CORS的实现

    IE8引入了XDR(XDomainRequest)类型。与XHR类似,但能实现安全可靠的跨域通信。所有XDR请求都是异步的,不能用它来创建同步请求。请求返回之后,会触发load事件,响应数据也会保存在responseText属性中。

    var xdr=new XDomainRequest();
    xhr.onload=function(){
      console.log(xhr.responseText);
    }
    xhr.onerror=function(){
      console.log("Error");
    }
    xdr.timeout=1000;
    xdr.ontimeout=function(){
      console.log("Request took too long");
    };
    xdr.open("get","http://www.cnblogs.com/yixiaoheng/");
    xdr.send(null);

    其他浏览器对CORS的实现

    Firefox3.5+、Safari4+、Chrome、iOS版Safari和Android平台中的WebKit都通过XMLHttpRequest对象实现对CORS的原生支持。在尝试打开不同来源的资源时,无需额外编写代码就可以触发这个行为。要请求位于另一个域中的资源,使用标准的XHR对象并在open()方法中传入绝对URL即可。

    var xhr=createXHR();
    xhr.onreadystatechange=function(){
      if(xhr.readyState==4){
        console.log(xhr.responseText);
      }else{
        console.log("Request was fail "+xhr.status);
      }
    };
    xhr.open("get","http://www.cnblogs.com/yixiaoheng/",true);
    xhr.send(null) 

    JSONP

    JSONP是JSON with padding(填充式JSON或参数式JSON)的简写,它是被包含在函数调用中的JSON 像这样callback({“name”:”Fany”})。

    JSONP由两部分组成:回调函数和数据。会掉函数是响应到来时应该在页面中调用的函数。回调函数的名字一般是在请求中指定的。而数据就是传入回调函数中的JSON数据。下面是一个典型的JSONP请求。

    http://freegeoip.net/json/?callback=handleResponse

    你可以使用$.getJSON()来处理返回数据。

    JSONP在开发人员中极为流行,主要原因是它非常简单易用。与图像Ping相比,它的优点在于能够直接访问响应文本,支持在浏览器和服务器之间的双向通信。

    缺点

    首先,JSONP是从其他域中加载代码执行。如果其他域不安全,很可能会在响应中夹带一些恶意的代码,而此时除了完全放弃JSONP调用之外,没有办法追究。

    其次,要确定JSONP请求是否失败并不容易。开发人员不得不使用计时器检测指定时间内是否接收了响应。

    服务器代理请求

     这个方案中心思想是在页面发送请求给本域服务器的一个代理脚本,代理脚本来完成对它域的请求,然后把结果返回给客户端。它的优点是可以完全模拟请求方法(无论GET还是POST),并把参数和客户端Cookies传递过去。

    这个方案能完成Jsonp不能完成的Post请求,但是实施起来比Jsonp麻烦的多。这里有一个PHP的实现方案可以参考,你可以先看下Yahoo团队的解决方案 JavaScript: Use a Web Proxy for Cross-Domain XMLHttpRequest Calls 因为方案是PHP我仅是了解重点,你需要Proxy!

    上面的三个方案主要解决Ajax跨域请求问题。

    还有个不一样的跨域方式是图像Ping

    图像Ping

    可以从任何网页中加载图像,不用担心跨域。这也是在线广告跟踪浏览量的主要方式,如跟踪用户点击页面或动态广告曝光次数。

    动态创建图像经常用于图像Ping.图像Ping是与服务器进行简单、单项的跨域通信的一种方式。请求的数据是通过查询字符串形式发送的,而相应可以是任意内容,但通常是像素图或204相应。通过图像Ping,浏览器得不到任何具体的数据,但通过侦听load和error,能知道响应式什么死后接收到的。例子:

    var img=new Image();
    img.onload=img.onerror=function(){
     console.log("Done");
    }
    img.src="http://example.com/test?name=fany";

    缺点

    一是只能发送get请求,二是无法访问服务器的相应文本。图像Ping只能用于浏览器与服务器间的单向通信。

    还有Flash跨域的解决方法,有几年不看这个了,所以没有仔细核实。罗列分享下吧

    Flash URLLoader

    Flash有自己的一套安全策略,服务器可以通过crossdomain.xml文件来声明能被哪些域的SWF文件访问,SWF也可以通过API来确定自身能被哪些域的SWF加载。当跨域访问资源时,例如从域www.a.com请求域www.b.com上的数据,我们可以借助Flash来发送HTTP请求。首先,修改域www.b.com上的crossdomain.xml(一般存放在根目录,如果没有需要手动创建) ,把www.a.com加入到白名单。其次,通过Flash URLLoader发送HTTP请求,最后,通过Flash API把响应结果传递给JavaScript。Flash URLLoader是一种很普遍的跨域解决方案,不过需要支持iOS的话,这个方案就无能为力了。

     Flash LocalConnection

    页面上的双向通信也可以通过Flash来解决,Flash API中有LocalConnection这个类,该类允许两个SWF之间通过进程通信,这时SWF可以播放在独立的Flash Player或者AIR中,也可以嵌在HTML页面或者是PDF中。遵循这个通信原则,我们可以在不同域的HTML页面各自嵌套一个SWF来达到相互传递数据的目的了。SWF通过LocalConnection交换数据是很快的,但是每次的数据量有40kb的大小限制。用这种方式来跨域通信过于复杂,而且需要了2个SWF文件,实用性不强。

     解决不同域之间JS交互又有哪些方式呢?

  • 相关阅读:
    java io系列23之 BufferedReader(字符缓冲输入流)
    java io系列22之 FileReader和FileWriter
    java io系列21之 InputStreamReader和OutputStreamWriter
    java io系列20之 PipedReader和PipedWriter
    java io系列19之 CharArrayWriter(字符数组输出流)
    java io系列18之 CharArrayReader(字符数组输入流)
    java io系列17之 System.out.println("hello world")原理
    java io系列16之 PrintStream(打印输出流)详解
    java io系列15之 DataOutputStream(数据输出流)的认知、源码和示例
    java io系列14之 DataInputStream(数据输入流)的认知、源码和示例
  • 原文地址:https://www.cnblogs.com/yixiaoheng/p/cross-domain-solution-1.html
Copyright © 2011-2022 走看看