jsonp原理和详解

 

 

在介绍JSONP之前,先简单的介绍一些JSONJSONJavaScript Object Notation的缩写,是一种轻量的、可读的基于文本的数据交换开放标准。源于JavsScript编程语言中对简单数据结构和关联数组的展示功能。它是仅含有数据对和简单括号结构的纯文本,因此可通过许多途径进行JSON消息的传递。

1. JSONP定义
 JSONP是英文JSONwith Padding的缩写,是一个非官方的协议。它允许在服务器端生成scripttags返回至客户端,通过javascript callback的形式来实现站点访问。 JSONP是一种script tag的注入,将server返回的response添加到页面实现特定功能。

2.JSONP由来

要解释JSONP的来由,先要说一下浏览器的“同源策略(SOP:Same OriginPolicy)简而言之,就是浏览器限制脚本程序只能和同协议、同域名、同端口的脚本进行交互,这包括共享和传递变量等。cookie的传递也是遵从同样策略。这就造成一些涉及到多个服务器的应用在整合时一些麻烦。跨域访问的问题造成A站点的Ajax代码无法访问B站点的数据。

如何解决跨域访问呢?那就要借助浏览器的一个特性:尽管浏览器不允许页面中的脚本程序跨域读取数据,但却允许HTML引用跨域的资源,如图片,CSS和脚本程序。对于脚本程序的引用比较特殊,它被浏览器解析以后,就和本地的脚本程序别无二致且可立即进行解释并执行。如在B站点的一个js文件,一个简单的提示框:alert(“This is Victor!”;。在A站点引用这个js,这个脚本就会在B站点的应用中执行,显示一个alert信息。由于站外脚本的引用是通过script tag来实现的,而脚本程序又可通过DOM的方式可以对HTML页面的所有标签进行控制(包括动态的创建script标签),这就可以实现通过调用站外程序对本地资源进行更改了。另外,通过<script>标记的使用,就可从服务端直接返回可执行的JavaScript函数调用或者JSON数据。

3. JSONP原理与实现
 首先在客户端注册一个callback,然后把callback的名字传给服务器。此时,服务器先生成 JSON数据。然后以JavaScript语法的方式,生成一个function, function名字就是传递上来的参数jsonp.

 
然后,将JSON数据直接以入参的方式,放置到function中,这样就生成了一段 js 语法的文档,返回给客户端。

 最后,在客户端浏览器中解析script标签,并执行返回的JavaScript文档,此时数据作为参数,传入到了客户端预先定义好的回调函数里(动态执行回调函数)

其实 JSONP是个很简单的一个东西。主要是利用了 <script/>标签对javascript文档的动态解析来实现。(其实也可以用eval函数)

JSONP实现代码:

Js代码  

1        < script type=" text/javascript" >

2        functionjsonpCallback(result){

3        alert(result.msg);

4        }

5        < /script>

6        < script type=" text/javascript"src="http://mydomain.com/jsonService?jsonp=jsonpCallback">

7        < /script>

< script  type="text/javascript" >      

        function  jsonpCallback(result){

             alert(result.msg);

        }      

< /script>      

< script  type="text/javascript"   src="http://mydomain.com/jsonService?jsonp=jsonpCallback">

< /script>

注解:

jsonCallback是获取跨域服务器上的JSON数据后的客户端的回调函数。

http://mydomain.com/jsonService?jsonp=jsonpCallback是获取跨域服务器JSON数据的接口,参数为回调函数的名字。返回的格式为:

Js代码  

8        jsonpCallback({ msg:'this is json data'} )

jsonpCallback({ msg:'this  is  json data'} )

4. jQuery与JSONP

从 1.2 版本开始,jQuery 拥有对 JSONP 回调的本地支持。如果指定了 JSONP 回调,就可以加载位于另一个域的 JSON 数据,回调的语法为:url?callback=?。jQuery 自动将? 替换为要调用的生成函数名。

jQuery回调函数:

Js代码  

9        jQuery.getJSON(url+"&callback=?",function(data) {

10    alert("Name: "+ data.name + ", Phone: "+ data.phone);

11    });

jQuery.getJSON(url+"&callback=?", function(data) {

    alert("Name: " +data.name + ", Phone: " + data.phone);

});

为此,jQuery 将一个全局函数附加到插入脚本时需要调用的窗口对象。另外,jQuery 也能优化非跨域调用。如果向同一个域发出请求,jQuery 就将其转化为普通 Ajax 请求。

5. JSONP的安全问题

在JavaScript 程序中有多种方法可动态地生成代码,最著名的函数之一就是eval()。该函数允许您将任意字符串做为 JavaScript 代码执行。然而,随意使用该函数是非常危险的。遗憾的是,一些使用广泛的 JavaScript 库在内部都直接使用 eval() 函数。JSON本身是安全的,不含有赋值和调用。但由于 JSON 是以 JavaScript 的一个子集为基础的,所以脚本内容会潜在地包含恶意代码。由于许多 JavaScript 库使用 eval() 函数将 JSON 转换成 JavaScript 对象,利用这点,攻击者就可以向这些库发送畸形的 JSON 对象,这样 eval() 函数就会执行这些恶意代码。为保护 JSON 的使用,可使用RFC 4627 中所定义的正则表达式确保 JSON 数据中不包含活动的部分。

JavaScript代码:

Js代码  

12    var my_JSON_object =!(/[^,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]/.test(

13    text.replace(/"(\\.|[^"\\])*"/g, ''))) &&

14    eval('('+ text + ')');

var my_JSON_object = !(/[^,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]/.test( 

            text.replace(/"(\\.|[^"\\])*"/g, ''))) && 

         eval('(' + text + ')');

6. JSONP的缺陷

JSONP 是构建 mashup 的强大技术,但不幸的是,它并不是所有跨域通信需求的万灵药。它有一些缺陷,必须认真考虑它们。

第一,也是最重要的一点,没有关于 JSONP 调用的错误处理。如果动态脚本插入有效,就执行调用;如果无效,就静默失败。失败是没有任何提示的。例如,不能从服务器捕捉到 404 错误,也不能取消或重新开始请求。不过,等待一段时间还没有响应的话,就不用理它了。(未来的 jQuery 版本可能有终止 JSONP 请求的特性)。

第二,JSONP 被不信任的服务使用时会很危险。因为 JSONP 服务返回打包在函数调用中的 JSON 响应,而函数调用是由浏览器执行的,这使宿主 Web 应用程序更容易受到各类攻击。如果打算使用 JSONP 服务,了解它能造成的威胁非常重要。

 

 

 

jsonp详解

jsonp详解

json相信大家都用的多,jsonp我就一直没有机会用到,但也经常看到,只知道是“用来跨域的”,一直不知道具体是个什么东西。今天总算搞明白了。下面一步步来搞清楚jsonp是个什么玩意。

同源策略

首先基于安全的原因,浏览器是存在同源策略这个机制的,同源策略阻止从一个源加载的文档或脚本获取或设置另一个源加载的文档的属性。看起来不知道什么意思,实践一下就知道了。

1.随便建两个网页

一个端口是2698,一个2701,按照定义它们是不同源的。

 

2.jQuery发起不同源的请求

2698端口的网页上添加一个按钮,Click事件随便发起两个向端口为2701域的请求。

$("#getOtherDomainThings").click(function(){

   $.get("http://localhost:2701/Scripts/jquery-1.4.4.min.js",function(data){

       console.log(data)

   })

 

   $.get("http://localhost:2701/home/index",function(data){

       console.log(data)

   })

})

根据同源策略,很明显会悲剧了。浏览器会阻止,根本不会发起这个请求。(not allowed by Access-Control-Allow-Origin

 

OK,原来jsonp是要解决这个问题的。

script标签的跨域能力

不知道大家知不知道CDN这个东西,例如微软的CDN,使用它,我们的网页可以不提供jQuery,由微软的网站帮我们提供:

<scriptsrc="http://ajax.aspnetcdn.com/ajax/jquery/jquery-1.8.0.js"type="text/javascript"></script>

 

回到我们的2698端口的网页,上面我们在Click事件里有一个对2701端口域的jQuery文件的请求,这次使用script标签来请求。

<scripttype="text/javascript"src="http://localhost:2701/Scripts/jquery-1.4.4.min.js"></script>

 

当然,200OK

 

同样是端口2698的网页发起对2701域的请求,放在script里设置scr属性的OK了,另一个方式就悲剧。利用script的跨域能力,这就是jsonp的基础。

利用script获取不同源的json

既然它叫jsonp,很明显目的还是json,而且是跨域获取。根据上面的分析,很容易想到:利用js构造一个script标签,把jsonurl赋给scriptscr属性,把这个script插入到dom里,让浏览器去获取。实践:

function CreateScript(src){

   $("<script><//script>").attr("src",src).appendTo("body")

}

添加一个按钮事件来测试一下:

$("#getOtherDomainJson").click(function(){

   $.get('http://localhost:2701/home/somejson',function(data){

       console.log(data)

   })

})

 

首先,第一个浏览器,http://localhost:2701/home/somejson这个Url的确是存在一个json的,而且在2698网页上用script标签来请求这个2701这个Url也是200OK的,但是最下面报js语法错误了。原来用script标签加载完后,会立即把响应当js去执行,很明显{"Email":"zhww@outlook.com","Remark":"我来自遥远的东方"}不是合法的js语句。

利用script获取异域的jsonp

显然,把上面的json放到一个回调方法里是最简单的方法。例如,变成这样:

 

如果存在jsonpcallback这个方法,那么jsonpcallback({"Email":"zhww@outlook.com","Remark":"我来自遥远的东方"})就是合法的js语句。

由于服务器不知道客户端的回调是什么,不可能hardcodejsonpcallback,所以就带一个QueryString让客户端告诉服务端,回调方法是什么,当然,QueryStringkey要遵从服务端的约定,上面的是”callback

添加回调函数:

function jsonpcallback(json){

   console.log(json)

}

把前面的方法稍微改改参数:

$("#getJsonpByHand").click(function(){

   CreateScript("http://localhost:2701/home/somejsonp?callback=jsonpcallback")

})

 

200OK,服务器返回jsonpcallback({"Email":"zhww@outlook.com","Remark":"我来自遥远的东方"}),我们也写了jsonpcallback方法,当然会执行。OK顺利获得了json。没错,到这里就是jsonp的全部。

利用jQuery获取jsonp

上面的方式中,又要插入script标签,又要定义一个回调,略显麻烦,利用jQuery可以直接得到想要的json数据,同样是上面的jsonp

$("#getJsonpByJquery").click(function(){

   $.ajax({

       url: 'http://localhost:2701/home/somejsonp',

       dataType: "jsonp",

       jsonp: "callback",

       success: function(data){

            console.log(data)

       }

   })

})

得到的结果跟上面类似。

总结

一句话就是利用script标签绕过同源策略,获得一个类似这样的数据,jsonpcallback是页面存在的回调方法,参数就是想得到的json

jsonpcallback({"Email":"zhww@outlook.com","Remark":"我来自遥远的东方"})

来源:http://www.cnblogs.com/lemontea/archive/2012/12/11/2812268.html

ADD 原生js:

<buttonid="btn">click</button>
<script type="text/javascript">
 function $(str){
 return document.getElementById(str)
 }
 function CreateScript(src) {
 varScrip=document.createElement('script');
 Scrip.src=src;
 document.body.appendChild(Scrip);
 }
 function jsonpcallback(json) {
 console.log(json);//Object {email="
中国", email2="中国222"}
 }
 $('btn').οnclick=function(){
 CreateScript("http://localhost:51335/somejson?callback=jsonpcallback")
 }
</script>

 

 

 

原文链接: http://wenku.baidu.com/view/20fed8637375a417876f8f12.html

 

 

相关视频课程推荐《站长必修课:网站是怎样做出来的?》https://edu.51cto.com/sd/3be5b

网站是怎样做出来的?

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值