【跨域】#001 JSONP原理解析【总结】

一、JSONP 是什么?

1.1 概念

JSONPJSON 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,也不能改变着一点!

参考文档:

时间: 2024-10-12 06:39:22

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

解决Ajax 跨域问题 - JSONP原理解析

解决Ajax 跨域问题 - JSONP原理解析 为什么会有跨域问题? - 因为有同源策略 同源策略是浏览器的一种安全策略,所谓同源指的是 请求URL地址中的 协议, 域名 和 端口 都相同,只要其中之一不相同就是跨域 同源策略主要为了保证浏览器的安全性 在同源策略下,浏览器**不允许**Ajax跨域获取服务器数据 http://www.example.com/detail.html 跨域请求: http://api.example.com/detail.html 域名不同 http://www.

Ajax跨域:Jsonp原理解析

推荐先看下这篇文章:JS跨域(ajax跨域.iframe跨域)解决方法及原理详解(jsonp) JavaScript是一种在Web开发中经常使用的前端动态脚本技术.在JavaScript中,有一个很重要的安全性限制,被称为“Same-Origin Policy”(同源策略).这一策略对于JavaScript代码能够访问的页面内容做了很重要的限制,即JavaScript只能访问与包含它的文档在同一域下的内容. JavaScript这个安全策略在进行多iframe或多窗口编程.以及Ajax编程时显得

跨域及JSONP原理

什么是跨域:a.com 域名下的js无法操作b.com或是c.a.com域名下的对象 为什么浏览器要引入跨域问题? 跨域问题来源于浏览器的同源策略,为啥要有这个策略呢? 为了安全.假设现在有a.com 和b.com 两个域,如果没有同源策略的限制,那么a.com就可以随随便便就去b.com 里面拿东西,甚至一些cookie信息(常用于存储登录信息),那么a.com只需要一段代码就可以获取你的cookie信息,从而冒充你的身份去登录网站. 当使用 AJAX 跨域访问资源 会受到同源策略影响,浏览器

跨域请求 JSONP 原理

js 中事先定义好回掉函数,回掉函数的参数就是跨域返回的值 后台返回调用的回掉函数

Ajax 跨域请求 jsonp获取json数据

遇到Ajax的跨域请求出问题 找了中解决办法如下: 参考内容:http://justcoding.iteye.com/blog/1366102 由于受到浏览器的限制,该方法不允许跨域通信.如果尝试从不同的域请求数据,会出现安全错误.如果能控制数 据驻留的远程服务器并且每个请求都前往同一域,就可以避免这些安全错误.但是,如果仅停留在自己的服务器上,Web 应用程序还有什么用处呢?如果需要从多个第三方服务器收集数据时,又该怎么办? 理解同源策略 同源策略阻止从一个域上加载的脚本获取或操作另一个域上的

Java跨域以及实现原理

最近研究了一下跨域,没接触之前我的印象就是配合单点登录的一种方式,后来在网上看到资料才知道不仅仅是这一种,用法很多,具体的可以去网上搜索. 一个众所周知的问题,Ajax直接请求普通文件存在跨域无权限访问的问题,甭管你是静态页面.动态网页.web服务.WCF,只要是跨域请求,一律不准.下面我就在自己本地用8081端口请求8081的接口看看会提示什么吧? 如上图所示,已经被浏览器拦截了,所以现在我们需要换jsonp的方法来获取服务器返回的数据. 服务端的接口如下: @RequestMapping(v

AJAX的跨域与JSONP

AJAX的跨域与JSONP 什么是AJAX的跨域请求 出于安全的考虑,如果你要从www.a.com通过Ajax来请求另外一个网站www.b.com的内容,浏览器是不允许你这样做的(不理解这里的安全是指什么?想想如果没有这个限制的话,黑客可以做些什么).那什么样的情况下算是跨域?域名不同那当然算是跨域了,例如a.com向b.com发送请求,这当然就是跨域了,不允许的.不过子域名不同(例如sub.a.com向www.a.com发送请求)甚至是同域名不同端口(例如a.com:80向a.com:8080

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

加油~ --WH 一.什么是javascript跨域问题? 域:服务器域名,唯一标识(协议,域名,端口)必须保证一致,说明域相同 跨域:在一个服务器上,去访问另一个服务器上,并且得到另一个服务器返回回来的值,这就是javascript跨域,其实简单点,之前我们做的ajax,都是在同域中访问,现在只是访问的服务器变成了另外的,不是同一台了.仅此而已.但是这样一变,之前的代码就不能用了. 二.解决javascript跨域问题 解决该问题,有很多种方式,我百度了一下,好像这就属于前端的范畴了,所以我决

JS跨域:jsonp、跨域资源共享、iframe+window.name

JS跨域:jsonp.跨域资源共享.iframe+window.name :https://www.cnblogs.com/doudoublog/p/8652213.html JS中的跨域 请求跨域有好多种, 一.跨域资源共享: 也就是设置服务端的header,可以指定哪些域名可以请求,也是最简单的跨域方式(自我感觉),并且可以支持post等等. //指定允许其他域名访问 'Access-Control-Allow-Origin:*'//或指定域 //响应类型 'Access-Control-A