1、Jsonp

Jsonp(json with padding)是JSON的一种“使用模式”,可用于解决主流浏览器的跨域数据访问的问题。

Jsonp是为了解决ajax跨域发送http请求出现的,利用Script标签的特性跨域。浏览器由于安全考虑,在编写ajax程序时,httprequest/xmlhttp都不能发送非本域的http请求,是被浏览器所禁止的。所以ajax本身是无法跨域的。

2、同源策略

www.a.com网页的ajax获取www.b.com接口的内容,由于您的网页域名是www.a.com,而您发送的ajax请求的目标域却是www.b.com。浏览器会阻止这一的请求,这就是所谓的同源策略。

同源是指:js脚本只能访问或者请求相同协议,相同domain(网址/ip),相同端口的页面。

我们知道,js脚本可以访问所在页面的所有元素。通过ajax技术,js也可以访问同一协议,同一个domain(ip),同一端口的服务器上的其他页面,请求到浏览器端之后,利用js就可以进行任意的访问。但是对于协议不同, 或者domain不同或者端口不同的服务器上的页面就无能为力了,完全不能进行请求。下面是例子:(http://localhost:57269/页面)

<script type="text/javascript">

    var xmlhttp;
if (window.XMLHttpRequest) {
xmlhttp = new XMLHttpRequest();
} else {
xmlhttp = ActionXObject("Microsoft.XMLHTTP");
} xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
console.log(xmlhttp.responseText);
}
}
var url = "http://localhost:51355/Common/Test";
xmlhttp.open("Get", url, true);
xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xmlhttp.send(); </script>

这里为了结果不受其他js库的干扰,使用了原生的XMLHttpRequest来处理,结果如下:

我们看到57269端口的ajax请求无法访问51355端口的页面。原因是“同源策略禁止读取“某某”的远程资源”。因为同源策略,普通的ajax无法跨域请求,解决这种问题的方式就是Jsonp。

3、Jsonp跨域的原理

我们发现凡是拥有"src"这个属性的标签都拥有跨域的能力,在页面上有三种资源是可以与页面本身不同源的。它们是:js脚本,css样式文件,图片,如下所示,它们是可以链接访问到不同源的资源的。

1)<script type="text/javascript" src="某个cdn地址" ></script>

2)<link type="text/css" rel="stylesheet" href="某个cdn地址" />

3)<img src="某个cdn地址" alt=""/>

而jsonp就是利用了<script>标签可以链接到不同源的js脚本,来达到跨域目的。当链接的资源到达浏览器时,浏览器会根据他们的类型来采取不同的处理方式,比如,如果是css文件,则会进行对页面 repaint,如果是img 则会将图片渲染出来,如果是script 脚本,则会进行执行,比如我们在页面引入了jquery库,为什么就可以使用 $ 了呢?就是因为jquery库被浏览器执行之后,会给全局对象window增加一个属性:$,所以我们才能使用 $ 来进行各种处理。(另外为什么要一般要加css放在头部,而js脚本放在body尾部呢,就是为了减少repaint的次数,另外因为js引擎是单线程执行,如果将js脚本放在头部,那么在js引擎在执行js代码时,会造成页面暂停。)

jQuery封装的 josnp 用法:

<script type="text/javascript">

    //第一种方式getJSON  callback=?,其中 ? 会自动替换为function(data)函数。
$.getJSON("http://localhost:51355/Common/Test?callback=?", function(data) {
var obj = JSON.parse(data); //很多网上的例子都是可以直接.age这样写的,但是我测试的时候无法这么做,必须要转一次josn,需要转josn,未能清楚为何没有自动为我转成json格式。
alert(obj.age);
}); //第二种方式ajax,设定请求方式为jsonp
$.ajax({
async: false,
url: "http://localhost:51355/Common/Test", //跨域的url
type: "GET",
dataType: 'jsonp', //返回格式
jsonp: "callback", //指定回调函数
data: "", //参数
success: function(data) {
var obj = JSON.parse(data); //很多网上的例子都是可以直接.age这样写的,但是我测试的时候无法这么做,必须要转一次josn,需要转josn,未能清楚为何没有自动为我转成json格式。
alert(obj.age);
}
});    //需要考证是否正确
   //jsonp: "callback", // 指定回调函数,这里名字可以为其他任意你喜欢的,比如callback,不过必须与下一行的GET参数一致
   //data: "name=jxq&email=feichexia@yahoo.com.cn&callback=?", // callback与上面的jsonp值一致
</script>

C# MVC代码:

//方式一
public ActionResult Test()
{
string callback = Request["callback"]; //jsonp1503629838983
string name = "cang";
string age = "";
string response = "{\"name\":\"" + name + "\",\"age\":\"" + age + "\"}";
System.Web.Script.Serialization.JavaScriptSerializer jss = new System.Web.Script.Serialization.JavaScriptSerializer();
string call = callback + "(" + jss.Serialize(response) + ")"; //jsonp1503629838983("{\"name\":\"cang\",\"age\":\"20\"}") return Content(call);
}
//方式二
public void Test()
{
string callback = Request["callback"]; //jsonp1503629838983
string name = "cang";
string age = "";
string response = "{\"name\":\"" + name + "\",\"age\":\"" + age + "\"}";
System.Web.Script.Serialization.JavaScriptSerializer jss = new System.Web.Script.Serialization.JavaScriptSerializer();
string call = callback + "(" + jss.Serialize(response) + ")"; //jsonp1503629838983("{\"name\":\"cang\",\"age\":\"20\"}")
  
Response.Write(call);
Response.End();
}

下面是我理解的josnp的原理(个人观点):

一个简单的JSONP请求可以通过一下代码实现:

<script type="text/javascript">    

    var callbackName = 'callback';
window[callbackName] = function(data) {
var obj = JSON.parse(data); //很多网上的例子都是可以直接.age这样写的,但是我测试的时候无法这么做,必须要转一次josn,需要转josn,未能清楚为何没有自动为我转成json格式。
alert(obj.age);
} var script = document.createElement('script');
script.src = 'http://localhost:51355/Common/Test?callback=' + callbackName;
document.body.appendChild(script); </script>

大概可以看出来,是创建了一个<script>标签,然后把我想请求的地址赋值给src。这样我是不是可以继续精简一下。

Html的head代码:

<head>
<script>
function callback(data) {
var obj = JSON.parse(data); //转josn
alert(obj.age);
}
</script>
<script src="http://localhost:51355/Common/Test?callback=callback" type="text/javascript"></script>
</head>

4、总结

1、这是我认为的josnp代码实现方式,应该是先创建了一个类似callback函数,然后创建一个<script>的标签,通过标签中的src指定的js脚本到达浏览器会执行的特性,发起请求告诉服务端函数名叫callback。html会把返回的字符串当作javascript代码来进行解析,然后返回的是一个函数包裹的josn数据callback(josn),即callback("{\"name\":\"cang\",\"age\":\"20\"}"),然后调动本地的callback函数输出josn。

2、jQuery是将jsonp封装成类似ajax的样子,是自动生成回调函数并把数据取出来供success属性方法来调用。

3、因为<script>标签的请求方式就是Get。所以Jsonp只能使用Get请求,即使jQuery方式的ajax里写的是post方式,最后也是get方式请求。

jQuery的ajax跨域 Jsonp原理的更多相关文章

  1. JQuery的Ajax跨域请求原理概述及实例

    今天在项目中需要做远程数据加载并渲染页面,直到开发阶段才意识到ajax跨域请求的问题,隐约记得Jquery有提过一个ajax跨域请求的解决方式,于是即刻翻出Jquery的API出来研究,发 JQuer ...

  2. Ajax操作如何实现跨域请求 (JSONP和CORS实现Ajax跨域的原理)

    由于浏览器存在同源策略机制,同源策略阻止ajax (XMLHttpRequest) 从一个源加载的文档或脚本获取或设置另一个源加载的文档的属性. 特别的:由于同源策略是浏览器的限制,所以请求的发送和响 ...

  3. JQuery实现ajax跨域

    AJAX 的出现使得网页可以通过在后台与服务器进行少量数据交换,实现网页的局部刷新.但是出于安全的考虑,ajax不允许跨域通信.如果尝试从不同的域请求数据,就会出现错误.如果能控制数据驻留的远程服务器 ...

  4. JQuery的Ajax跨域请求的

    JQuery的Ajax跨域请求的(Ajax) 什么是jsonp格式呢?API原文:假设获取的数据文件存放在远程server上(域名不同.也就是跨域获取数据),则须要使用jsonp类型.使用这样的类型的 ...

  5. PHP+JQuery实现ajax跨域

    jQuery实现ajax跨域 1.dataType:'jsonp'2.type: 'get'3.把要传的参数以url方式传出去  url:'http://gameapi.feiliu.com/lqzg ...

  6. jQuery使用ajax跨域请求获取数据

    jQuery使用ajax跨域请求获取数据  跨域是我在日常面试中经常会问到的问题,这词在前端界出现的频率不低,主要原因还是由于安全限制(同源策略, 即JavaScript或Cookie只能访问同域下的 ...

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

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

  8. 使用JSONP,jQuery的ajax跨域获取json数据

    网上找了很多资料,写的不错,推荐下: 1.深入浅出JSONP--解决ajax跨域问题 (http://www.cnblogs.com/chopper/archive/2012/03/24/240394 ...

  9. jQuery的ajax跨域实现

    今天有人问我跨域ajax请求是否可以发送,之前没接触过此类问题,没答上,后来查了下,以下备忘. 我在本地建了三个站点,并设置了host文件模拟跨子域和跨全域 coolkissbh.com blog.c ...

随机推荐

  1. c++ int string互转

    1. ){ monthNumber = "; itoa(i+,iCharArray,); monthNumber += iCharArray; } else { itoa(i+,iCharA ...

  2. LinuxMint系统下Gate One的安装指南

    1. Gate One简介 前面有两个随笔介绍过开源软件tty.js和wetty在Linux的安装.Tty.js和wetty都是采用Node.js实现的开源Web-based ssh.今天来介绍另一个 ...

  3. storm学习之六-使用Maven 生成jar包多种方式

    Maven可以使用mvn package指令对项目进行打包,如果使用java -jar xxx.jar执行运行jar文件,会出现"no main manifest attribute, in ...

  4. git恢复本地删除的文件夹取消增加的文件

    git项目中有时候会在本地增加或者删除了一些文件或者文件夹,但是又不想提交,一般情况下,我们取消本地所有修改: git checkout . 取消指定文件修改: git checkout filena ...

  5. ABBYY FineReader错误代码142和55

    在使用ABBYY FineReader 12OCR文字识别软件创建PDF文件时,有时会出现以下错误提示:内部程序错误..\Src\SpecialFontFactory.cpp,142和内部程序错误.. ...

  6. Mapper method 'com.autoyol.mapper.trans.AccountLogMapper.getTotalIncomByMemNoLastest attempted to return null from a method with a primitive return type (int).解决方法

    1.打开日志输出,降低日志级别. <AppenderRef ref="console" level="trace"></AppenderRef ...

  7. 源码分析五(HashSet的内部实现)

    一:首先来看看Hashset的继承体系 public class HashSet<E> extends AbstractSet<E> implements Set<E&g ...

  8. SpEL、PropertyPlaceholderConfigurer与@Value、#{}、${}

    概念 SpEL:Spring EL表达式 PropertyPlaceholderConfigurer:即org.springframework.beans.factory.config.Propert ...

  9. SpringMVC由浅入深day01_12参数绑定(12.1参数绑定过程_12.2默认支持的类型_12.3简单类型)

    12 参数绑定 处理器适配器在执行Handler之前需要把http请求的key/value数据绑定到Handler方法形参数上. 注解适配器对RequestMapping标记的方法进行适配,对方法中的 ...

  10. 车牌、手机、身份证、等敏感信息 屏蔽 替换 、中文转unicode编码 函数

    应工作要求,需要对展示的内容进行敏感信息替换.琢磨的一些时间,编写的函数匹配率还是比较高的. 顺便说下思路,使用的是正则匹配替换和字符串替换.函数可以再改进. 先把需要匹配的内容写好相应的正则,然后进 ...