`
zhsq_java
  • 浏览: 61871 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类

转一个大神的ajax跨域请求总结留待以后参考

    博客分类:
  • JS
阅读更多
http://www.cnblogs.com/SanMaoSpace/p/3144851.html
1.什么是跨域?
跨域,JavaScript出于安全方面的考虑,不允许跨域调用其他页面的对象。简单地理解就是因为JavaScript同源策略的限制,a.com 域名下的js无法操作b.com或是c.a.com域名下的对象。
同源策略,它是由Netscape提出的一个著名的安全策略。现在所有支持JavaScript 的浏览器都会使用这个策略。所谓同源是指,域名,协议,端口相同。当一个浏览器的两个tab页中分别打开来 百度和谷歌的页面当一个百度浏览器执行一个脚本的时候会检查这个脚本是属于哪个页面的,即检查是否同源,只有和百度同源的脚本才会被执行。
更详细的说明可以看下表:

URL 说明 是否允许通信
http://www.a.com/a.js
http://www.a.com/b.js 同一域名下 允许
http://www.a.com/lab/a.js
http://www.a.com/script/b.js 同一域名下不同文件夹 允许
http://www.a.com:8000/a.js
http://www.a.com/b.js 同一域名,不同端口 不允许
http://www.a.com/a.js
https://www.a.com/b.js 同一域名,不同协议 不允许
http://www.a.com/a.js
http://70.32.92.74/b.js 域名和域名对应ip 不允许
http://www.a.com/a.js
http://script.a.com/b.js 主域相同,子域不同 不允许
http://www.a.com/a.js
http://a.com/b.js 同一域名,不同二级域名(同上) 不允许(cookie这种情况下也不允许访问
http://www.cnblogs.com/a.js
http://www.a.com/b.js 不同域名 不允许
特别注意两点:
(1).如果是协议和端口造成的跨域问题“前台”是无能为力的,
(2).在跨域问题上,域仅仅是通过“URL的首部”来识别而不会去尝试判断相同的ip地址对应着两个域或两个域是否在同一个ip上。
“URL的首部”指window.location.protocol +window.location.host,也可以理解为“Domains, protocols and ports must match”。

2.跨域请求数据解决方案
(1).document.domain+iframe的设置
对于主域相同而子域不同的例子,可以通过设置document.domain的办法来解决。
(2).动态创建Script
虽然浏览器默认禁止了跨域访问,但并不禁止在页面中引用其他域的JS文件,并可以自由执行引入的JS文件中的function(包括操作cookie、Dom等等)。
(3).利用iframe和location.hash
这个办法比较绕,但是可以解决完全跨域情况下的脚步置换问题。原理是利用location.hash来进行传值。
(4).Window.name实现的跨域数据传输
iframe的src属性由外域转向本地域,跨域数据即由iframe的window.name从外域传递到本地域。这个就巧妙地绕过了浏览器的跨域访问限制,但同时它又是安全操作。
(5).使用HTML5 postMessage
HTML5中最酷的新功能之一就是 跨文档消息传输Cross Document Messaging。
(6).利用flash
上述,六种方式都可以处理JavaScript的跨域请求数据问题,详细参见:Rain Man的《JavaScript跨域总结与解决办法》。
除了上面六种方式,大家平时估计都在用脚本框架开发,在JQuery框架和ExtJs框架中处理JS跨域问题,常用JSONP来处理。

3.什么是JSONP?
JSONP(JSON with Padding)是一个非官方的协议,它允许在服务器端集成Script Tags返回至客户端,通过Javascript callback的形式实现跨域访问(这仅仅是JSONP简单的实现形式)。
由于同源策略的限制,XMLHttpRequest只允许请求当前源(域名、协议、端口)的资源,为了实现跨域请求,可以通过script标签实现跨域请求,然后在服务端输出JSON数据并执行回调函数,从而解决了跨域的数据请求。

4..JSONP如何产生的?
(1).跨域访问无权限。
众所周知的问题,Ajax直接请求普通文件存在跨域无权限访问的问题,不管是静态页面、动态网页、web服务、WCF,只要是跨域请求,都无权限;
(2)."src"属性标签有跨域能力。
发现在Web页面上调用js文件时则不受是否跨域的影响(不仅如此,拥有"src"属性的标签都拥有跨域能力,比如<script>、<img>、<iframe>);
(3).将数据装进JS格式数据。
如果想通过纯Web端(ActiveX控件、服务端代理、HTML5之Websocket等方式不算)跨域访问数据就只有一种可能,就是在远程服务器上设法把数据装进js格式的数据里,供客户端调用和进一步处理;
(4).JSON格式承载数据适合。
有一种JSON的纯字符数据格式可以简洁的描述复杂数据,更妙的是JSON还被JS原生支持,所以在客户端几乎可以随心所欲的处理这种格式的数据;
(5).动态生成JSON格式数据。
Web客户端可以通过与调用脚本一模一样的方式,来调用跨域服务器上动态生成的js格式文件,显而易见,服务器之所以要动态生成JSON文件,目的在于把客户端需要的数据装入进去。
(6).JSON数据成功回调到客户端。
客户端在对JSON文件调用成功之后,也就获得了自己所需的数据,剩下的就是按照自己需求进行处理和展现了,这种获取远程数据的方式看起来非常像AJAX,但实质上是不一样。
(7).形成一种非正式传输协议JSONP。
为了便于客户端使用数据,逐渐形成了一种非正式传输协议,人们把它称作JSONP,该协议的一个要点就是允许用户传递一个callback参数给服务端,然后服务端返回数据时会将这个callback参数作为函数名来包裹住JSON数据,这样客户端就可以随意定制自己的函数来自动处理返回的数据。

5.JSONP的工作原理
JSONP的原理:创建一个回调函数,动态创建Script标签,然后在远程服务上调用这个函数并且将JSON 数据形式作为参数传递,完成回调。将JSON数据填充进回调函数,进行相关的逻辑处理,或许这就是JSONP的JSON+Padding的含义。
(1).跨域简单原理
新建一个asp.net的web程序,添加sample.html网页和一个test.js文件,代码如下:
sample.html的代码:


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
  <head>
    <title>test</title>
    <script type="text/javascript" src="test.js"></script>
  </head>
  <body>
  </body>
</html>

test.js的代码:

alert("success");
打开sample.html后会跳出"success”这样的这样的信息框,这似乎并不能说明什么, 跨域问题到底怎么解决呢?
现在模拟非同源的环境,把上面的Web程序叫做A程序,再新建一个Web程序叫做B程序,将A程序的test.js文件移除然后拷贝到B程序中。将两个程序都运行起来,Visual Studio会启动内置服务器,假设A程序是localhost:20001,B程序是localhost:20002,这就模拟了一个非同源的环境了(虽然域名相同但端口号不同,所以是非同源的)。

现在改下A程序sample.html里的代码,因为test.js文件在B程序上了,url也就变成了localhost:20002。

sample.html部分代码:

<script type="text/javascript" src="http://localhost:20002/test.js"></script>
请保持AB两个Web程序的运行状态,当你再次刷新A程序localhost:20001/sample.html的时候,和原来一样跳出了"success"的对话框,这样就成功访问到了非同源的B程序localhost:20002/test.js这个所谓的远程服务了。到这里,大家应该已经大概明白如何跨域访问的原理了。
<script>标签的src属性并不被同源策略所约束,所以可以获取任何服务器上脚本并执行。

(2).跨域实现CallBack
继续修改代码,实现JSONP的JavaScript callback形式。
修改程序A中sample的代码:


<script type="text/javascript">
  //回调函数
  function callback(data) {
    alert(data.message);
  }
</script>
<script type="text/javascript" src="http://localhost:20002/test.js"></script>

程序B中test.js的代码:

//调用callback函数,并以json数据形式作为阐述传递,完成回调
callback({message:"success"});
这其实就是JSONP的简单实现模式,或者说是JSONP的原型:创建一个回调函数,然后在远程服务上调用这个函数并且将JSON 数据形式作为参数传递,完成回调。
(3).跨域实现动态JS脚本
怎么让远程js知道它应该调用的本地函数叫什么名字?毕竟是jsonp的服务者都要面对很多服务对象,而这些服务对象各自的本地函数都不相同。只要服务端提供的js脚本是动态生成的就可以,这样调用者可以传一个参数过去告诉服务端“我想要一段调用XXX函数的js代码,请你返回给我”,于是服务器就可以按照客户端的需求来动态生成js脚本并响应了。
程序A中sample的代码:


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
    <script type="text/javascript">
    // 得到航班信息查询结果后的回调函数
    var flightHandler = function(data){
        alert('你查询的航班结果是:票价 ' + data.price + ' 元,余票 ' + data.tickets + ' 张。');
    };
    // 提供jsonp服务的url地址(不管是什么类型的地址,最终生成的返回值都是一段javascript代码)
    var url = "http://flightQuery.com/jsonp/flightResult.aspx?code=CA1998&callback=flightHandler";
    // 创建script标签,设置其属性
    var script = document.createElement('script');
   script.setAttribute("type","text/javascript");
   script.setAttribute('src', url);
    // 把script标签加入head,此时调用开始
    document.getElementsByTagName('head')[0].appendChild(script);
    </script>
</head>
<body>
</body>
</html>

这样不直接把远程js文件写死,而是编码实现动态查询,而这也正是jsonp客户端实现的核心部分,其重点也就在于如何完成jsonp调用的全过程。
看到调用的url中传递了一个code参数,告诉服务器我要查的是CA1998次航班的信息,而callback参数则告诉服务器,本地回调函数叫做flightHandler,所以请把查询结果传入这个函数中供本地调用。
程序B中test.js的代码:

flightHandler({
"code": "CA1998",
"price": 1780,
"tickets": 5
});
我们看到,传递给flightHandler函数的是一个json,它描述了航班的基本信息。运行一下页面,成功弹出提示窗口,jsonp的执行全过程顺利完成!

6.JQuery和ExtJs实现JSONP
(1).JQuery的JSONP跨域实现
<1>.$.getJSON
jQuery框架支持JSONP,可以使用$.getJSON(url,[data],[callback])方法(详细可以参考http://api.jquery.com/jQuery.getJSON/)。继续修改程序A的代码,改用jQuery的getJSON方法来实现(下面的例子没用用到向服务传参,所以只写了getJSON(url,[callback])):

<script type="text/javascript" src="http://code.jquery.com/jquery-latest.js"></script>
<script type="text/javascript">
$.getJSON("http://localhost:20002/MyService.ashx?callback=?",function(data){
alert(data.name + " is a a" + data.sex);
});
</script>
要注意的是在url的后面必须添加一个callback参数,这样getJSON方法才会知道是用JSONP方式去访问服务,callback后面的那个问号是内部自动生成的一个回调函数名。这个函数名可以debug看一下,比如jQuery17207481773362960666_1332575486681。

<2>.$.ajax
假如说我们想指定自己的回调函数名,或者说服务上规定了固定回调函数名该怎么办呢?可以使用$.ajax方法来实现(参数较多,详细可以参见http://api.jquery.com/jQuery.ajax)。


<script type="text/javascript" src="http://code.jquery.com/jquery-latest.js"></script>
<script type="text/javascript">
$.ajax({
    url:"http://localhost:20002/MyService.ashx?callback=?",
    dataType:"jsonp",
    jsonpCallback:"person",
    success:function(data){
        alert(data.name + " is a a" + data.sex);
    }
});
</script>

jsonpCallback就是指定我们自己的回调方法名person,远程服务接受callback参数的值就不再是自动生成的回调名,而是person。dataType是指定按照JSOPN方式访问远程服务。

(2).ExtJs的JSONP跨域实现
<1>.Ext.data.JsonP.request
ExtJS4.1的Ext.data.JsonP.request实现跨域访问:


//跨域请求,MsgUrl为其他站点地址
Ext.data.JsonP.request({
    url: MsgUrl + '/Home/InitializeComet',
    timeout: 300000,
    params: { loginId: LoginId },
    callbackKey: "jsonPCallback",
    success: function(result) {
        if (result.rettype == 'true') {
            me.Comet.privateToken = result.msg;
            me.RegisterComet();
        } else {
            alert(result.msg);
        }
    },
    failure: function(result) {
        alert(result);
    }
});               

其中跨域请求的要点是类名:Ext.data.JsonP和callbackKey的参数。
“jsonPCallback”该名称将作为Jsonp请求的方法名传递到服务器端,获取该请求的URL:
http://10.0.13.64:89/Home/InitializeComet?loginId=0001&jsonPCallback=Ext.data.JsonP.callback1&_dc=1370687739484

<2>.Ext.data.ScriptTagProxy


var ss = new Ext.data.ScriptTagProxy({
  //url: 'http://10.128.3.104/edi/rest/GetBillCaseInfo',
    url: 'testjson.do',
    callbackParam: "_callback",
    headers: { 'Authorization': 'Basic YWRtaW46YWRtaW4xMjM=' }
});
ss.load({ '_out': 'json' },
  new Ext.data.JsonReader(
    { root: "ROWSET.ROW" },
    [{ name: 'CaseCode', mapping: 'CaseCode' },{ name: 'CaseName', mapping: 'CaseName'}]),
    function (recordsBlock, arg, isok) {
        alert(Ext.encode(recordsBlock));
        alert(Ext.encode(recordsBlock.records[0].data));
}
);


Ext.Ajax.request({
    url: 'http://10.128.3.104/edi/rest/GetBillCaseInfo',
    //url: 'testjson.do',
    scriptTag: true,
    success: function (req) {
        alert(req.responseText);
    },
    failure: function (req) {
        alert(req.responseText);
    },
    headers: { 'Authorization': 'Basic YWRtaW46YWRtaW4xMjM=' },
    params: { _out: 'json' }
});

7.AJAX与JSONP的异同
(1).Ajax和Jsonp是两种技术。
Ajax和Jsonp这两种技术在调用方式上“看起来”很像,目的也一样,都是请求一个URL,然后把服务器返回的数据进行处理,因此JQuery和EXT等框架都把Jsonp作为Ajax的一种形式进行了封装;
(2).Ajax和Jsonp实现原理不同。
Ajax和Jsonp在本质实现上有差别。Ajax的核心是通过XmlHttpRequest获取非本页内容,而Jsonp的核心则是动态添加<script>标签来调用服务器提供的js脚本。所以说,其实Ajax与jsonp的区别不在于是否跨域,ajax通过服务端代理一样可以实现跨域,Jsonp本身也不排斥同域的数据的获取;
(3).Ajax和Jsonp都是非强制性协议。
Jsonp是一种方式或者说非强制性协议,如同Ajax一样,它也不一定非要用Json格式来传递数据,如果你愿意,字符串都行,只不过这样不利于用Jsonp提供公开服务。
总而言之,Jsonp不是Ajax的一个特例,哪怕Jquery、Ext等巨头把Jsonp封装进了Ajax,也不能改变这一点!
分享到:
评论

相关推荐

    解决ajax跨域请求问题

    然而,跨域请求是Ajax的一个常见问题,由于浏览器的同源策略限制,Ajax请求只能向与当前页面同源的服务器发送。本文将深入探讨如何解决Ajax跨域请求的问题。 首先,理解“同源策略”是解决问题的关键。同源策略是...

    Jquery跨域Ajax请求测试

    以下是一个简单的jQuery跨域Ajax请求的示例: ```javascript $.ajax({ type: "GET", url: "http://example.com/remote-service", // 远程服务地址 dataType: "jsonp", jsonpCallback: "handleResponse", // 回...

    ajax跨域请求WebService.asmx

    【Ajax跨域请求WebService.asmx】是一个常见的Web开发技术应用场景,主要涉及到JavaScript的Ajax技术、C#编程语言以及ASP.NET的WebService组件。Ajax(Asynchronous JavaScript and XML)是一种在不刷新整个页面的...

    ajax跨域请求jsonp前后台代码

    基于ajax方式的跨域请求jsonp的前后台代码

    ajax跨域请求

    本篇文章将通过一个具体的示例(JSP页面+后台实例)来详细介绍如何实现AJAX跨域请求。 #### 二、同源策略概述 同源策略(Same-origin policy)是浏览器的一项安全措施,用于限制一个源上的网页脚本与另一个源上的...

    ajax跨域请求demo.zip

    这个"ajax跨域请求demo.zip"压缩包提供了一个关于如何实现Ajax跨域请求的示例,涉及到前后端的交互。 首先,我们关注"前端代码"部分。前端通常使用JavaScript库如jQuery来实现Ajax请求。jQuery的`$.ajax()`方法是...

    ajax处理跨域请求

    但是,对于非简单请求(如POST、PUT、DELETE等),浏览器会先发送一个预检请求(OPTIONS),询问服务器是否允许跨域。此时,服务器需要响应`Access-Control-Allow-Methods`、`Access-Control-Allow-Headers`等相关...

    jsonpajax跨域请求

    JSONP(JSON with Padding)和AJAX是两种常见的在JavaScript中实现跨域数据请求的技术。在Web开发中,由于浏览器的同源策略限制,JavaScript不能直接向其他域名发送请求,但JSONP和AJAX通过特定的方式绕过了这个限制...

    html通过 ajax jsonp跨域请求接收和传送数据

    在Web开发中,跨域(Cross-Origin)是一个常见的问题,由于浏览器的安全策略限制,JavaScript通常不能直接访问不同源(协议+域名+端口)的资源。然而,为了实现某些功能,比如用户登录、数据获取等,我们需要打破这...

    ajax 跨域请求问题 jquery jsonp

    **Ajax跨域请求问题与jQuery JSONP解析** 在Web开发中,Ajax技术被广泛用于实现页面的异步更新,但浏览器的同源策略(Same-Origin Policy)限制了Ajax请求只能向同源(协议、域名、端口均相同)的服务器发送。这在...

    利用JQuery jsonp实现Ajax跨域请求json数据

    由于`&lt;script&gt;`标签不受同源策略限制,可以加载任何源的JavaScript文件,开发者会在请求的URL中添加一个回调函数名参数,服务器接收到请求后,会将数据包裹在这个回调函数中返回,客户端执行这个函数,从而实现了...

    Ajax跨域请求解决方案-JSONP

    当`&lt;script&gt;`标签的`src`属性指向一个提供JSON数据的URL时,浏览器会发送GET请求,并接收返回的JavaScript代码执行。JSONP就是将JSON数据包裹在一个JavaScript函数调用中,这样返回的数据就能被前端的JavaScript代码...

    ajax跨域解决办法

    4. **服务器代理**:在服务器端设置一个代理,将客户端的AJAX请求转发到目标服务器,然后将结果返回给客户端。这通常通过修改服务器配置或编写中间件实现,例如Apache或Nginx的反向代理功能。 5. **Flash跨域**:...

    juery mobile使用ajax跨域请求服务器的小实例

    以下是一个简单的示例,展示了如何使用jQuery Mobile和Ajax进行跨域请求: ```html &lt;!DOCTYPE html&gt; &lt;title&gt;jQuery Mobile 跨域请求示例 , initial-scale=1"&gt; ...

    怎样实现Ajax 跨域访问

    请求时,在URL中添加一个回调函数名作为参数,服务器收到请求后返回一个函数调用,其中包含所需的数据。 **案例展示:** ```javascript function loadContent() { var s = document.createElement('script'); s....

    JQury实现Ajax跨域访问

    服务器返回一个JavaScript函数调用,该函数带有要返回的数据。客户端通过创建`&lt;script&gt;`标签并设置其`src`属性为跨域URL,从而加载并执行返回的函数,从而达到数据交互的目的。jQuery的`$.getJSON()`和`$.ajax()`...

    ajax跨域请求调用webservice接口+视频教程

    【标题】"Ajax跨域请求调用WebService接口"是一个关键的技术点,主要涉及到Web开发中的异步数据交互和跨域安全策略。在Web应用程序中,Ajax(Asynchronous JavaScript and XML)技术允许我们在不刷新整个页面的情况...

    demo跨域ajax_DEMO_ajax跨域_

    本示例“demo跨域ajax_DEMO_ajax跨域”着重解决C#后端与JavaScript前端之间的跨域限制。这里我们将深入探讨什么是跨域、为何会产生跨域问题以及如何通过C#和Ajax实现跨域通信。 首先,我们需要了解什么是跨域。根据...

Global site tag (gtag.js) - Google Analytics