一、JSONP 是什么?

1.1 概念

JSONP(JSON with Padding)是资料格式 JSON 的一种“使用模式”,可以让网页从别的网域要资料。由于同源策略,一般来说位于 server1.example.com 的网页无法与不是 server2.example.com 的服务器沟通,而 HTML 的 <script> 元素是一个例外。

利用 <script> 元素的开源策略,从其他域 动态的获取 数据,这就是JSONP。(让使用者利用 script 元素注入的方式绕开同源策略)

 

1.1.1 思路

  1. 一个返回JSON数据的URL接口
  2. JavaScript 底层会用 XMLHttpRequest 跟这个 URL接口 请求数据
  3. 为了让浏览器可以在 <script> 元素执行,返回的数据必须是可执行的 JavaScript脚本

 

1.2 JSONP前缀

在 JSONP 的使用模式里,该 URL 回传的是由函数呼叫包起来的动态生成 JSON,这就是JSONP 的“填充(padding)”或是“前辍(prefix)”的由来。

惯例上浏览器提供回调函数的名称当作送至服务器的请求中命名查询参数的一部份,例如:

<script type="text/javascript" src="http://server2.example.com/RetrieveUser?UserId=1823&jsonp=parseResponse"> </script>

服务器会在传给浏览器前将 JSON 数据填充到回调函数(parseResponse)中。

浏览器得到的回应已不是单纯的资料叙述而是一个脚本。

在本例中,浏览器得到的是:

parseResponse({"Name": "Cheeso", "Id" : 1823, "Rank": 7})

这个前缀可以是

  1. 某个回调函数
  2. 变量赋值
  3. 其他JavaScript脚本

JSONP 要求(也就是使用 JSONP 模式的请求)的回应不是 JSON 也不被当作 JSON 解析——回传内容可以是任意的运算式,甚至不需要有任何的 JSON,不过惯例上填充部份还是会触发函数调用的一小段 JavaScript 片段,而这个函数呼叫是作用在 JSON 格式的资料上的。

1.3  JSONP 的安全问题

使用远端网站的 script 标签会让远端网站得以注入任何的内容至网站里。如果远端的网站有 JavaScript 注入漏洞,原来的网站也会受到影响.现在有一个正在进行计划在定义所谓的 JSON-P 严格安全子集,使浏览器可以对 MIME 类别是“application/json-p”请求做强制处理。如果回应不能被解析为严格的 JSON-P,浏览器可以丢出一个错误或忽略整个回应。

粗略的 JSONP 部署很容易受到跨网站的伪造要求(CSRF/XSRF)的攻击。因为 HTML <script> 标签在浏览器里不遵守同源策略,恶意网页可以要求并取得属于其他网站的 JSON 资料。当使用者正登入那个其他网站时,上述状况使得该恶意网站得以在恶意网站的环境下操作该 JSON 资料,可能泄漏使用者的密码或是其他敏感资料。

1.4 JSONP DEMO

1.4.1 跨域js文件中的代码(当然指符合web脚本安全策略的),web页面也是可以无条件执行的。

远程服务器remoteserver.com根目录下有个remote.js文件代码如下:

alert('跨域调用成功');

本地服务器localserver.com下有个jsonp.html页面代码如下:

<html xmlns="http://www.w3.org/1999/xhtml">

<head>

<title></title>

<script type="text/javascript"src="http://remoteserver.com/remote.js"></script>

</head>

<body>

</body>

</html>

页面会弹出一个 弹出框,显示跨域调用成功。

1.4.2 现在 在 jsonp.html页面定义一个函数,然后在远程remote.js中传入数据进行调用。

jsonp.html页面代码如下:

<html xmlns="http://www.w3.org/1999/xhtml">

<head>

<title></title>

<script type="text/javascript">

varlocalHandler=function(data){

alert('我是本地函数,可以被跨域的remote.js文件调用,远程js带来的数据是:'+data.result);

};

</script>

<script type="text/javascript"src="http://remoteserver.com/remote.js"></script>

</head>

<body>

</body>

</html>

remote.js文件代码如下:

localHandler({“result”:”我是远程js带来的数据”});
运行之后查看结果,页面成功弹出提示窗口,显示本地函数被跨域的远程js调用成功,并且还接收到了远程js带来的数据。

跨域远程获取数据的目的基本实现了,但是出现了一个问题?  怎么让远程的JS 站点它 应该调用的本地函数名呢?

1.4.3 服务端返回的JS脚本,是动态生成的

调用者把参数传到服务端,然后服务端生成相对应的脚本,并返回。

看jsonp.html页面的代码:

<html xmlns="http://www.w3.org/1999/xhtml">

<head>

<title></title>

<script type="text/javascript">

// 得到航班信息查询结果后的回调函数

varflightHandler=function(data){

alert('你查询的航班结果是:票价 '+data.price+' 元,'+'余票 '+data.tickets+' 张。');

};

// 提供jsonp服务的url地址(不管是什么类型的地址,最终生成的返回值都是一段javascript代码)

varurl="http://flightQuery.com/jsonp/flightResult.aspx?code=CA1998&callback=flightHandler";

// 创建script标签,设置其属性

varscript=document.createElement('script');

script.setAttribute('src',url);

// 把script标签加入head,此时调用开始

document.getElementsByTagName('head')[0].appendChild(script);

</script>

</head>

<body>

</body>

</html>

调用者传了一个code参数到服务端,告诉服务端要查 CA1998 航班的信息,而callback 参数告诉服务器,本地回调函数名叫 flightHandler。

OK,服务器很聪明,这个叫做flightResult.aspx的页面生成了一段这样的代码提供给jsonp.html(服务端的实现这里就不演示了,与你选用的语言无关,说到底就是拼接字符串):

flightHandler({
"code":"CA1998",
"price":1780,
"tickets":5
});

二、jQuery对JSONP的实现(目的:便于与用户界面交互,方便调用,提高开发效率)

依然沿用上面那个航班信息查询的例子,假定返回jsonp结果不变:

<!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>UntitledPage</title>
<script type="text/javascript"src=jquery.min.js"></script>
<script type="text/javascript">
jQuery(document).ready(function(){
$.ajax({
type:"get",
async:false,
url:"http://flightQuery.com/jsonp/flightResult.aspx?code=CA1998",
dataType:"jsonp",
jsonp:"callback",//传递给请求处理程序或页面的,用以获得jsonp回调函数名的参数名(一般默认为:callback)
jsonpCallback:"flightHandler",//自定义的jsonp回调函数名称,默认为jQuery自动生成的随机函数名,也可以写"?",jQuery会自动为你处理数据
success:function(json){
alert('您查询到航班信息:票价: '+json.price+' 元,余票: '+json.tickets+' 张。');
},
error:function(){
alert('fail');
}
});
});
</script>
</head>
<body>
</body>
</html>

为什么没有写flightHandler函数?竟然运行成功?

这就是jQuery的功劳了,jquery在处理jsonp类型的ajax时自动生成回调函数并把数据取出来供success属性方法来调用。

 

Ajax 与 JSONP 的异同

  1. ajax和jsonp这两种技术在调用方式上“看起来”很像,目的也一样,都是请求一个url,然后把服务器返回的数据进行处理,因此jquery和ext等框架都把jsonp作为ajax的一种形式进行了封装;
  2. 但ajax和jsonp其实本质上是不同的东西。ajax的核心是通过XmlHttpRequest获取非本页内容,而jsonp的核心则是动态添加<script>标签来调用服务器提供的js脚本。
  3. 所以说,其实ajax与jsonp的区别不在于是否跨域,ajax通过服务端代理一样可以实现跨域,jsonp本身也不排斥同域的数据的获取。
  4. 还有就是,jsonp是一种方式或者说非强制性协议,如同ajax一样,它也不一定非要用json格式来传递数据,如果你愿意,字符串都行,只不过这样不利于用jsonp提供公开服务。

总而言之,jsonp不是ajax的一个特例,哪怕jquery等巨头把jsonp封装进了ajax,也不能改变着一点!

参考文档:

【跨域】#001 JSONP原理解析【总结】的更多相关文章

  1. Ajax跨域:Jsonp原理解析

    推荐先看下这篇文章:JS跨域(ajax跨域.iframe跨域)解决方法及原理详解(jsonp) JavaScript是一种在Web开发中经常使用的前端动态脚本技术.在JavaScript中,有一个很重 ...

  2. JQuery实现Ajax跨域访问--Jsonp原理

    JavaScript是一种在Web开发中经常使用的前端动态脚本技术.在JavaScript中,有一个很重要的安全性限制,被称为“Same-Origin Policy”(同源策略).这一策略对于Java ...

  3. 跨域及JSONP原理

    什么是跨域:a.com 域名下的js无法操作b.com或是c.a.com域名下的对象 为什么浏览器要引入跨域问题? 跨域问题来源于浏览器的同源策略,为啥要有这个策略呢? 为了安全.假设现在有a.com ...

  4. 跨域篇--JSONP原理

    一篇文章让你明白 jsonp原理详解 什么是JSONP? 先说说JSONP是怎么产生的: 其实网上关于JSONP的讲解有很多,但却千篇一律,而且云里雾里,对于很多刚接触的人来讲理解起来有些困难,着用自 ...

  5. Java跨域以及实现原理

    最近研究了一下跨域,没接触之前我的印象就是配合单点登录的一种方式,后来在网上看到资料才知道不仅仅是这一种,用法很多,具体的可以去网上搜索. 一个众所周知的问题,Ajax直接请求普通文件存在跨域无权限访 ...

  6. 【原】Java跨域以及实现原理

     前言:最近研究了一下跨域,主要是jsonp的实现,经过测试后总结如下: 一个众所周知的问题,Ajax直接请求普通文件存在跨域无权限访问的问题,甭管你是静态页面.动态网页.web服务.WCF,只要是跨 ...

  7. JS跨域方法及原理

        JS跨域分析判断 JS跨域:在不同域之间,JS进行数据传输或通信.比如ajax向不同的域请求数据.JS获取iframe中的页面中的值(iframe内外不同域) 只要协议.端口.域名有一个不同则 ...

  8. jQuery(三) javascript跨域问题(JSONP解决)

    加油~ --WH 一.什么是javascript跨域问题? 域:服务器域名,唯一标识(协议,域名,端口)必须保证一致,说明域相同 跨域:在一个服务器上,去访问另一个服务器上,并且得到另一个服务器返回回 ...

  9. jquery跨域解决方案JSONP

    1.在互联网中我们的计算机是通过IP来定位的,但是IP比较难记忆,因此通过domain name(域名)来取代IP 2.什么是跨域? (1)默认浏览器为了安全问题,禁止了xmlhttprequest跨 ...

随机推荐

  1. 我的Vue之小功能统计

    摘要:项目中经常会要用到大大小小的功能,所以我在这里进行一个汇总,后面会持续添加至这篇博客,希望当你遇到这个功能时,我的博客能够对你有帮助,(上一篇博客说要在收假后写一篇博客做一个年终总结,想了半天不 ...

  2. Linux系统资源查看 之 资源信息

    1. 系统 版本信息 内核版本 使用 uname 命令: -a : 查看所有系统信息 -r : 查看内核版本信息 -s : 查看内核名称 代码如下: [niesh@niesh ~]$ uname -a ...

  3. @Resource和@Autowired区别

    @Resource和@Autowired都是做bean的注入时使用 历史:  @Autowired     属于Spring的注解    org.springframework.beans.facto ...

  4. Oracle表闪回功能

    1.启用表闪回首先要在表上支持行移动(在数据字典中设置标识来标识该操作可能会改变行ID,即同一条数据闪回成功后主键都一样,但行ID其实已经发生变化了) SQL> alter table base ...

  5. spring data jpa 的简单使用

    先说简单一下JPA 概念:JPA(Java Persistence API)是Sun官方提出的Java持久化规范.它为Java开发人员提供了一种对象/关联映射工具来管理Java应用中的关系数据. 影响 ...

  6. Myeclipse安装与破解

    安装包+破解包 链接:https://pan.baidu.com/s/1G4mYsTOMDixyr2UmdqqY5A 提取码:a2n8 红色框框内的是安装包,蓝色框框内的是破解包 安装过程中比较简单, ...

  7. 为什么说 LINQ 要胜过 SQL

    如果你还没有沉溺于 LINQ,就会想这有啥大惊小怪的.SQL 并没有坏掉,为什么还要对它进行修补呢? 为什么我们还需要另外一种查询语言呢? 流行的说法是 LINQ 同 C#(或者 VB)集成在了一起, ...

  8. thymeleaf 标签使用方法

    使用thymeleaf首先添加依赖,<dependency><groupId>org.springframework.boot</groupId><artif ...

  9. git使用总结(常用命令)

    前言 写这篇文章的目的是让新手能够操作git管理自己的代码,可能你知道git的各种命令但是对其使用顺序并不熟,比如我.所以有必要整合一篇关于命令使用步骤的文章,图片用的人家的,也没询问让不让用,可能会 ...

  10. CentOS7.4+MongoBD3.6.4集群(Shard)部署以及大数据量入库

    前言 mongodb支持自动分片,集群自动的切分数据,做负载均衡.避免上面的分片管理难度.mongodb分片是将集合切合成小块,分散到若干片里面,每个片负责所有数据的一部分.这些块对应用程序来说是透明 ...