`
crystalwiner
  • 浏览: 90571 次
  • 性别: Icon_minigender_2
  • 来自: 深圳
社区版块
存档分类
最新评论

AJAX跨域问题

 
阅读更多

    这几天被跨域问题困扰了很久,现在整理下思绪,以备不时之需。
  

     由于安全方面的考虑,JS被限制了跨域访问的能力,但是有时候我们希望能够做一些合理的跨域访问的事情,那么怎么办呢?


这里分两类情况:


一、基于同一父域的子域之间页面的访问;参见如下3个domain域:sina.com、news.sina.com、mail.sina.com;它们有相同的父域taobao.com。


二、基于不同父域页面之间的访问;参见如下3个domain域:taobao.com、baidu.com、sina.com.cn;它们具有不同的父域。


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

 


方案1:服务器Proxy


域A 的页面JS需要访问域B下的链接获取数据,该方案在域A的服务器端建立一个Proxy程序(可能是PHP\ASP、servlet等任何服务端程序),域A的页面 JS直接调用本域下的Proxy程序,proxy程序负责将请求发送给域B下的链接并获取到数据,最后再通过Proxy将数据返回给页面JS使用。


经过的访问流程就是: 域A下JS --> 域A 下Proxy -- > 域B下的链接


Proxy方案优点是可以适用用于几乎所有的跨域访问,而且只需要要一个域中进行开发,另一个域可以提供任何类型格式的数据。缺点是这种方案经过了中间Proxy,所以延迟可能稍微大一点,并且会加重本域服务器的负荷,开发工作量也稍微大一点。


方案2:隐藏iframe、共享domain :


通常情况下,我们会用与下面类似的代码来创建一个XMLHttpRequest对象:


factories = [

function() { return new XMLHttpRequest(); },

function() { return new ActiveXObject("Msxml2.XMLHTTP"); },

function() { return new ActiveXObject("Microsoft.XMLHTTP"); }

];

function newRequest() {

 for(var i = 0; i < factories.length; i++) {

   try{

    var factory = factories[i];

    return factory();

  } catch(e) {}

 }

 return null;

}



 

上面的代码中引用ActiveXObject,是为了兼容IE6系列浏览器。每次我们调用newRequest函数,就获得了一个刚刚创建的 Ajax对象,然后用这个Ajax对象来发送HTTP请求。例如,下面的代码向abc.example.com发送了一个GET请求:


var request = newRequest();

request.open("GET", "http://abc.example.com" );

request.send(null);


 

假设上面的代码包含在一个abc.example.com域名下的页面里,则这个GET请求可以正常发送成功,没有任何问题。然而,如果现在要向def.example.com发送请求,则出现跨域问题,JavaScript引擎抛出异常。


解决的办法是,在def.example.com域下放置一个跨域文件,假设叫crossdomain.html;然后将前面的 newRequest函数的定义移到这个跨域文件中;最后像之前修改document.domain值的做法一样,在crossdomain.html文件和 abc.example.com域下调用Ajax的页面顶端,都加上:


 

<script type="text/javascript">

document.domain = "example.com";

</script>


 

 

为了使用跨域文件,我们在abc.example.com域下调用Ajax的页面中嵌入一个隐藏的指向跨域文件的iframe,例如:

<iframe name="xd_iframe" style="display:none" src="http://def.example.com/crossdomain.html"></iframe>

这时abc.example.com域下的页面和跨域文件crossdomain.html都在同一个域(example.com)下,我们可以在abc.example.com域下的页面中去调用crossdomain.html中的newRequest函数:

var request = window.frames["xd_iframe"].newRequest();

这样获得的request对象,就可以向http://def.example.com发送HTTP请求了。


隐藏iframe方式也很简单,它可以处理任何返回的数据格式,但它只适用在具有同一个父域下的跨域请求上,并且要求其他域得配合开发,即需要设置document.domain。


方案3:
JSONP 跨域GET请求 通过Script标签) :


在域A页面http://news.sina.com/test.htm 的head中写一个空的Script标签:


 

<html>  
<head>  
 <mce:script id="remoteScript" type="text/javascript" src=""/><!--  
<head>  
<body>  
<script type="text/javascript" >  
 Var remoteScript=document.getElementById("remoteScript");  
 remoteScript.src="www.baidu.com/xxxxx.do";//域B的链接  
 alert(remote.test);//使用域B返回的JSON数据   
 alert(f[0]);  
// --></mce:script>  
</body>  
</html> 







 [注意]:这种方案要求域B返回的数据必须是合法的JSON格式或者如JS文件的格式;



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


JSONP的缺点则是:它只支持GET请求而不支持POST等其它类型的HTTP请求;它只支持跨域HTTP请求这种情况,不能解决不同域的两个页面之间如何进行JavaScript调用的问题。而且它 对返回的数据格式要求有点严格,只能是Json格式数据,如果是其他格式的数据,那么这种方法就无能为力了。


方案4: 利用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 version="1.0"?>

<cross-domain-policy>

<allow-access-from domain="example2.com" />

</cross-domain-policy>


方案5: window.postMessage


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


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


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


otherWindow.postMessage(message, targetOrigin);

 

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

 

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实现的跨域功能同样强大,并且使用简单,效率更高,但缺点是它目前在浏览器兼容方面有待提高。


方案6: 通过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长度的限制,要考虑对数据进行分段传输等。


方案7: getJSON+callback方法

在加载了jquery的前提下,用法如下:

$.post($action,{'type':'us'},function callback($data,$code){
   if($code != 'success'){
    alert('aa');

   }else{   
    alert('hello!');

   }
  },"json"); 

分享到:
评论

相关推荐

    Ajax跨域问题及其解决方案.docx

    ### Ajax跨域问题及其解决方案 #### 一、Ajax跨域问题概述 在现代Web开发中,前后端分离架构越来越流行。这种模式下,前端页面与后端服务通常部署在不同的服务器上,甚至可能位于不同的域名下。当浏览器发起对不同...

    IE7 Ajax跨域问题

    标题 "IE7 Ajax跨域问题" 涉及到的是在使用Ajax技术在Internet Explorer 7(IE7)浏览器中处理跨域请求时遇到的挑战。在Web开发中,Ajax(Asynchronous JavaScript and XML)是一种在不刷新整个页面的情况下与服务器...

    解决ajax跨域问题

    为了解决AJAX跨域问题,开发者可以采用以下几种策略: 1. JSONP(JSON with Padding) JSONP是一种绕过同源策略的方法,它利用了`&lt;script&gt;`标签不受同源策略限制的特点。JSONP的工作原理是服务器提供一个可被调用的...

    ajax跨域问题的解决办法

    ajax跨域问题的解决办法 ajax跨域问题是指在使用ajax技术时遇到的跨域限制问题,即ajax请求不能跨域访问其他域的服务器资源。这种限制是由于浏览器的同源策略所引起的,同源策略规定一个域下的脚本只能访问该域下的...

    ajax跨域问题!

    ### AJAX跨域问题详解 #### 一、引言 在Web开发中,由于浏览器的安全策略限制,同源策略(Same-origin policy)对于不同来源的数据访问进行了严格的限制,从而导致了跨域问题的发生。本篇文章将深入探讨AJAX跨域...

    Ajax跨域问题 解决方案

    ### Ajax跨域问题解决方案 #### 一、什么是Ajax跨域 **原理:** Ajax跨域问题的核心在于浏览器的“同源策略”。同源策略是一种安全措施,用于限制一个域名下的文档或脚本如何与另一个来源的资源进行交互。简单来说...

    ajax跨域问题的解决办法.rar

    本教程将详细探讨如何解决Ajax跨域问题。 一、同源策略 同源策略是浏览器为了保障用户安全而实施的一种机制,它限制了Web页面只能读取同源(协议+域名+端口相同)的资源。当Ajax尝试向不同源发送请求时,浏览器会...

    Ajax跨域问题详细解读

    Ajax跨域问题详解 在Web开发中,Ajax(Asynchronous JavaScript and XML)技术被广泛用于实现页面的异步更新,提升用户体验。然而,随着跨域安全策略的实施,Ajax请求并非总能畅通无阻,这就是所谓的Ajax跨域问题。...

    扩展ServiceBase类解决Ajax跨域问题

    总结来说,SuperMap iClient提供的扩展`ServiceBase`类的方法,使得开发者能够方便地解决Ajax跨域问题,确保Web应用在不同源之间能顺利进行数据交换。通过自定义服务类并覆盖关键方法,我们可以灵活控制CORS策略,...

    解决ajax跨域请求问题

    解决Ajax跨域问题有多种方法: 1. JSONP(JSON with Padding):JSONP是一种利用动态插入`&lt;script&gt;`标签来绕过同源策略的方法。服务器返回一个JavaScript函数调用,带有请求的数据作为参数。例如,服务器返回`...

    AJAX跨域问题[整理].pdf

    AJAX跨域问题主要涉及到浏览器的安全机制——同源策略,这是一种限制JavaScript脚本只能访问与当前页面同源(协议、域名、端口均相同)的网页数据的策略。当需要从不同源获取数据时,AJAX请求会受到限制,导致跨域...

    前端基础-Ajax跨域问题的解决方案.docx

    在前端开发中,Ajax 跨域问题是一个常见的挑战,它源于浏览器的安全策略——同源策略。同源策略限制了从一个源(域名、协议和端口的组合)加载的网页与另一个源进行交互的能力,以保护用户的隐私和安全。然而,这种...

    ajax跨域解决办法

    AJAX跨域问题的出现是由于浏览器的安全机制,旨在防止恶意网站通过脚本访问其他网站的数据,保护用户隐私。但是,在某些场景下,比如前后端分离的应用、API接口调用等,跨域请求是必要的。针对这一需求,有多种解决...

    Ajax跨域问题及解决方案(jsonp,cors)

    在前台通过动态添加script标签及src属性,表面看上去与ajax极为相似,但是,这和ajax并没有任何关系;为了便于使用及交流,逐渐形成了一中非正式传输协议,人们把它称作 jsonp 。 代码如下: html: &lt;body&gt; ...

    Spring Boot Redis Session 共享(Ajax 跨域)

    本教程将详细讲解如何在Spring Boot项目中利用Redis来存储和共享Session,并解决Ajax跨域问题。 首先,我们需要理解Spring Boot中的Session管理。默认情况下,Spring Boot使用内存中的HttpSession来存储用户会话...

    关于ajax跨域问题的几种常见解决方案,附代码。

    什么是跨域,跨域出现的场景,模拟跨域,springmvc下解决跨域,springboot下解决跨域。绝对原创。

    cors技术解决ajax跨域

    **CORS技术详解:解决AJAX跨域问题** 在Web开发中,由于浏览器的同源策略限制,AJAX请求只能向同一源(协议+域名+端口)发送,这在跨域请求时会遇到障碍。为了解决这个问题,CORS(Cross-Origin Resource Sharing,...

Global site tag (gtag.js) - Google Analytics