【跨域】#001 JSONP原理解析【总结】
一、JSONP 是什么?
1.1 概念
JSONP(JSON with Padding)是资料格式 JSON 的一种“使用模式”,可以让网页从别的网域要资料。由于同源策略,一般来说位于 server1.example.com 的网页无法与不是 server2.example.com 的服务器沟通,而 HTML 的 <script>
元素是一个例外。
利用 <script>
元素的开源策略,从其他域 动态的获取 数据,这就是JSONP。(让使用者利用 script 元素注入的方式绕开同源策略)
1.1.1 思路
- 一个返回JSON数据的URL接口
- JavaScript 底层会用 XMLHttpRequest 跟这个 URL接口 请求数据
- 为了让浏览器可以在 <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})
这个前缀可以是
- 某个回调函数
- 变量赋值
- 其他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 的异同
- ajax和jsonp这两种技术在调用方式上“看起来”很像,目的也一样,都是请求一个url,然后把服务器返回的数据进行处理,因此jquery和ext等框架都把jsonp作为ajax的一种形式进行了封装;
- 但ajax和jsonp其实本质上是不同的东西。ajax的核心是通过XmlHttpRequest获取非本页内容,而jsonp的核心则是动态添加<script>标签来调用服务器提供的js脚本。
- 所以说,其实ajax与jsonp的区别不在于是否跨域,ajax通过服务端代理一样可以实现跨域,jsonp本身也不排斥同域的数据的获取。
- 还有就是,jsonp是一种方式或者说非强制性协议,如同ajax一样,它也不一定非要用json格式来传递数据,如果你愿意,字符串都行,只不过这样不利于用jsonp提供公开服务。
总而言之,jsonp不是ajax的一个特例,哪怕jquery等巨头把jsonp封装进了ajax,也不能改变着一点!
参考文档:
【跨域】#001 JSONP原理解析【总结】的更多相关文章
- Ajax跨域:Jsonp原理解析
推荐先看下这篇文章:JS跨域(ajax跨域.iframe跨域)解决方法及原理详解(jsonp) JavaScript是一种在Web开发中经常使用的前端动态脚本技术.在JavaScript中,有一个很重 ...
- JQuery实现Ajax跨域访问--Jsonp原理
JavaScript是一种在Web开发中经常使用的前端动态脚本技术.在JavaScript中,有一个很重要的安全性限制,被称为“Same-Origin Policy”(同源策略).这一策略对于Java ...
- 跨域及JSONP原理
什么是跨域:a.com 域名下的js无法操作b.com或是c.a.com域名下的对象 为什么浏览器要引入跨域问题? 跨域问题来源于浏览器的同源策略,为啥要有这个策略呢? 为了安全.假设现在有a.com ...
- 跨域篇--JSONP原理
一篇文章让你明白 jsonp原理详解 什么是JSONP? 先说说JSONP是怎么产生的: 其实网上关于JSONP的讲解有很多,但却千篇一律,而且云里雾里,对于很多刚接触的人来讲理解起来有些困难,着用自 ...
- Java跨域以及实现原理
最近研究了一下跨域,没接触之前我的印象就是配合单点登录的一种方式,后来在网上看到资料才知道不仅仅是这一种,用法很多,具体的可以去网上搜索. 一个众所周知的问题,Ajax直接请求普通文件存在跨域无权限访 ...
- 【原】Java跨域以及实现原理
前言:最近研究了一下跨域,主要是jsonp的实现,经过测试后总结如下: 一个众所周知的问题,Ajax直接请求普通文件存在跨域无权限访问的问题,甭管你是静态页面.动态网页.web服务.WCF,只要是跨 ...
- JS跨域方法及原理
JS跨域分析判断 JS跨域:在不同域之间,JS进行数据传输或通信.比如ajax向不同的域请求数据.JS获取iframe中的页面中的值(iframe内外不同域) 只要协议.端口.域名有一个不同则 ...
- jQuery(三) javascript跨域问题(JSONP解决)
加油~ --WH 一.什么是javascript跨域问题? 域:服务器域名,唯一标识(协议,域名,端口)必须保证一致,说明域相同 跨域:在一个服务器上,去访问另一个服务器上,并且得到另一个服务器返回回 ...
- jquery跨域解决方案JSONP
1.在互联网中我们的计算机是通过IP来定位的,但是IP比较难记忆,因此通过domain name(域名)来取代IP 2.什么是跨域? (1)默认浏览器为了安全问题,禁止了xmlhttprequest跨 ...
随机推荐
- Java Date SimpleDateFormat
public static void main(String[] args) { long millis = 1492741275301L; Calendar calendar = Calendar. ...
- 在百度搜索里展现网站LOGO
我们经常在百度搜索一些网站可以看到一个网站在百度上展示的三个部分: 网站的名称 如(趣学车) 网站的描述 一段比较详细的对网站的介绍 网站的logo,一张logo图片 如下图 ------ 接下来我们 ...
- Vertica使用Database Designer创建完整的设计
Vertica Database Designer 分析逻辑架构,示例数据库可以分析实力查询. 创建可自动部署或手动部署的物理架构设计(一组投射) 任何不具备数据库专业知识的人员均可使用 可以随时运行 ...
- Jupyter Notebook 快速入门[转]
Jupyter Notebook(此前被称为 IPython notebook)是一个交互式笔记本,支持运行 40 多种编程语言.在本文中,我们将介绍 Jupyter notebook 的主要特性,以 ...
- C#关于操作符重载与转换
随便写写 首先,假设我们有一个Person类型 其类型定义如下 class Person { public string Name { get; set; } = "Person" ...
- Android全屏的两种方法
在开发中我们经常需要把我们的应用设置为全屏,这里我所知道的有俩中方法,一中是在代码中设置,另一种方法是在配置文件里改! 一.在代码中设置: [java] view plain copy package ...
- 手动实现一个简单的ArrayList
import org.omg.CORBA.PUBLIC_MEMBER; import java.io.Serializable; import java.util.*; import java.uti ...
- 关于shader的学习
教程地址:https://onevcat.com/2013/07/shader-tutorial-1 因为想做一些特效,所以想稍微了解一下shader的代码,一下是一些笔记 // Upgrade NO ...
- MangoDB的C#驱动库(.net framewokr 4.0)
编写运维工具,需要联接MangoDB 基于我陈旧的技术栈,就用c#开发了 驱动库下载地址记录到至此,需要的可以下载 注意,此驱动是老版本的,只支持.net framewokr 4.0 看了半天,觉得够 ...
- [js常用]连续播放音频
许多音频连续播放.有的时候音频过大会分成多个音频.播放的时候需要连续播放 <!DOCTYPE HTML> <html> <head> <meta charse ...