什么引起了ajax不能跨域请求的问题?
ajax本身实际上是通过XMLHttpRequest对象来进行数据的交互,而浏览器出于安全考虑,不允许js代码进行跨域操作,所以会警告。
有什么完美的解决方案么?
解决方案有不少,但是只能是根据自己的实际情况来选择。
跨域的安全限制都是指浏览器端来说的,服务器端是不存在跨域安全限制的。所以针对这2种情况衍生出2类跨域解决方案,一类是服务器端做中转类似代理方式,一类是js处理浏览器端的真正跨域访问。
具体情况有:
- 本域和子域的相互访问: www.aa.com和book.aa.com用document.domain = "aa.com";
- 本域和其他域的相互访问: www.aa.com和www.bb.com用XMLHttpRequest访问代理,既服务器端代理方式
- 本域和其他域的相互访问: www.aa.com和www.bb.com用JS创建动态脚本,<script>标签的src属性实现跨域访问
解决方法:
- 如果想做到数据的交互,那么www.aa.com和book.aa.com必须由你来开发才可以。可以将book.aa.com用iframe添加到www.aa.com的某个页面下,在www.aa.com和iframe里面都加上document.domain = "aa.com",这样就可以统一域了,可以实现跨域访问。就和平时同一个域中镶嵌iframe一样,直接调用里面的JS就可以了。
- 这种情形是最经常遇到的,也是用的最多的了。就是www.aa.com和www.bb.com你只能修改一个,也就是另外一个是别人的,人家告诉你你要取得数据就访问某某连接参数是什么样子的,最后返回数据是什么格式的。而你需要做的就是让你的服务器端充当中转代理,让服务器去别人的网站上取得数据,再返回给浏览器端。
服务器端充当中转代理方式有很多可以由服务器端程序实现,也可以修改服务器配置实现,下面举例Apache重写(mod_rewrite proxy模式)方式:
在Apache的安装目录下的conf/httpd.conf文件添加如下语句:
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule rewrite_module modules/mod_rewrite.so
RewriteEngine On
RewriteRule ^/_proxy/(.*)$
http:// $1 [P,L]
|
这样就可以把其他网站的url映射为本服务器的/_proxy/目录下面,例如可以这么访问百度http://html.duqn.com/_proxy/www.baidu.com
这个的区别就是请求是使用<script>标签来请求的,这个要求也是两个域都是由你来开发才行。原理就是JS文件注入,在本域内的aa.com内生成一个JS标签,它的SRC指向请求的另外一个域bb.com的某个页面b,b返回数据即可,可以直接返回JS的代码。因为script的src属性是可以跨域的。具体看代码,这个也比较简单。
aa.com/a.jsp
<script type= "text/javascript" >
function myTest(data) {
alert(data);
}
</script>
|
bb.com/b.jsp页面代码如下:
$(param.jsoncallback)({ "name" :
"Zhang Huihua" ,
"QQ" :
"350863780" })
|
b.jsp页面通过$(param.jsoncallback)得到浏览器端随后要回调的js function name:myTest
实际上客户端接收到的response如下:myTest({"name": "Zhang Huihua", "QQ": "350863780"})
jQuery浏览器端跨域访问
目前jQuery$.ajax()支持get方式的跨域,这其实是采用jsonp的方式来完成的。其原理就是上面第三种方式,<script>标签的src属性实现跨域访问
真实案例代码如下:
$.ajax({
url: http: //跨域的dns/index!searchJSONResult.action,
type: "GET" ,
dataType: 'jsonp' ,
data: {name:”ZhangHuihua”},
timeout: 5000,
success: function (json) { //客户端jquery预先定义好的callback函数,成功获取跨域服务器上的json数据后,会动态执行这个callback函数
alert(json);
},
error: function (xhr, ajaxOptions, thrownError){
alert( "Http status: " + xhr.status +
" " + xhr.statusText +
"\najaxOptions: " + ajaxOptions +
"\nthrownError:" +thrownError +
"\n" +xhr.responseText);
}
});
|
注意:
$.getJSON( "http://跨域的dns/index!searchJSONResult.action?name1=" +value1+ "&jsonCallback=?" ,
function (json){
// 执行代码
});
|
这种方式其实是上例$.ajax({..}) api的一种高级封装,有些$.ajax api底层的参数就被封装而不可见了.
这样,jquery就会拼装成如下的url get请求
http://跨域的dns/index!searchJSONResult.action?&jsonCallback=jsonp1236827957501&_=1236828192549&name=ZhangHuihua
jsonCallback自定义的jsonp回调函数名称,默认为jQuery自动生成的随机函数名,也可以写"?",jQuery会自动为你处理数据.
在响应端(http://跨域的dns/index!searchJSONResult.action),
通过jsoncallback = request.getParameter("jsoncallback")得到jquery端随后要回调的js function name:jsonp1236827957501
然后response的内容为一个Script Tags:"jsonp1236827957501("+按请求参数生成的json数组+")";
jquery就会通过回调方法动态加载调用这个js tag:jsonp1236827957501(json数组);
这样就达到了跨域数据交换的目的.
jsonp的最基本的原理是:动态添加一个<script>标签,而script标签的src属性是没有跨域的限制的。这样说来,这种跨域方式其实与ajax XmlHttpRequest协议无关了.
这样其实"jQuery AJAX跨域问题"就成了个伪命题了,jquery $.ajax方法名有误导人之嫌.
如果设为dataType: 'jsonp',这个$.ajax方法就和ajax XmlHttpRequest没什么关系了,取而代之的则是JSONP协议.
JSONP是一个非官方的协议,它允许在服务器端集成Script tags返回至客户端,通过javascript callback的形式实现跨域访问
JSONP即JSON with Padding。由于同源策略的限制,XmlHttpRequest只允许请求当前源(域名、协议、端口)的资源。如果要进行跨域请求,
我们可以通过使用html的script标记来进行跨域请求,并在响应中返回要执行的script代码,其中可以直接使用JSON传递javascript对象。
这种跨域的通讯方式称为JSONP。
jsonCallback函数jsonp1236827957501(....):是浏览器客户端注册的,获取跨域服务器上的json数据后,回调的函数
Jsonp原理:
首先在客户端注册一个callback (如:'jsoncallback'),然后把callback的名字(如:jsonp1236827957501)传给服务器。
此时,服务器先生成json数据。
然后以javascript语法的方式,生成一个function , function名字就是传递上来的参数'jsoncallback'的值jsonp1236827957501 .
最后将json数据直接以入参的方式,放置到function中,这样就生成了一段js语法的文档,返回给客户端。
客户端浏览器,解析script标签,并执行返回的javascript文档,此时javascript文档数据,作为参数,
传入到了客户端预先定义好的callback函数(如上例中jquery $.ajax()方法封装的的success: function (json))里.(动态执行回调函数)
可以说jsonp的方式原理上和<script src="http://跨域/...xx.js"></script>是一致的(qq空间就是大量采用这种方式来实现跨域数据交换的) .JSONP是一种脚本注入(Script Injection)行为,所以也有一定的安全隐患.
注意,jquey是不支持post方式跨域的.
虽然采用post +动态生成iframe是可以达到post跨域的目的,但这样做是一个比较极端的方式,不建议采用.
也可以说get方式的跨域是合法的,post方式从安全角度上,被认为是不合法的,万不得已还是不要剑走偏锋..
浏览器端跨域访问的需求看来也引起w3c的注意了,看资料说html5 WebSocket标准支持跨域的数据交换,应该也是一个将来可选的跨域数据交换的解决方案.
分享到:
相关推荐
JS跨域访问解决
js解决跨域访问问题,在用js访问web后台方法的时候,有时候会遇到跨域访问的问题。文档中介绍了跨域访问产生的原因以及相应的解决办法及代码示例。
js跨域访问解决方案总结,不同域名下cookie相互操作
JS跨域访问解决方案总结.。总结了记住JS跨域访问解决方案。
JS跨域访问解决方案总结[参照].pdf
JS跨域访问解决方案总结.pdf
Javascript跨域访问解决方案 个人在网上搜集的资料,用于传输信息,不提倡下载
通过HTTPClient界面在JSP中嵌入iframe子界面跨域时,无法获取跨域界面的属性值的问题
javascript 跨域访问 综合解决方案
在浏览器查看一个pdf文件时常常不知道怎么显示,这个资源可以很好的帮到你,而且还附有跨域的解决办法。
本篇文章主要介绍了解决ajax不能访问本地文件问题(利用js跨域原理),具有一定的参考价值,有兴趣的可以了解一下。
arcgis api for js 4.x 在tomcat离线部署后,跨域访问问题,彻底解决。
JS跨域访问解决方案的总结.doc跨域请求,顾名思义,就是一个站点中的资源去访问另外一个不同域名站点上的资源。这种情况很常见,比如说通过style标签加载外部样式表文件、通过 img 标签加载外部图片、通过 script ...
主要介绍了Vue.js 中 axios 跨域访问错误问题及解决方法,非常不错,具有一定的参考借鉴价值 ,需要的朋友可以参考下
1、基于wcf框架对Rest架构的web服务实现; 2、支持javascript的多种方式跨域访问(GET/POST/PUT/DELETE); 3、解决服务调用参数传递的动态设计数据格式(Xml/Json);
本demo为通过jquery 来进行json的跨域访问的小例子。简单易懂!
报表的下拉控件中用到一个名为creatPopup()的js方法,该方法本书是拒绝跨域访问的。 js跨域问题,是在一个域下的页面中通过js访问另一个不同域下的数据对象,出于安全性考虑,几乎所有浏览器都不允许这种跨域访问。 ...