同源策略

ajax之所以需要“跨域”,罪魁祸首就是浏览器的同源策略。即,一个页面的ajax只能获取这个页面相同源或者相同域的数据。

如何叫“同源”或者“同域”呢?——协议、域名、端口号都必须相同。例如:

根据同源策略,我自己做的一个网页 http://localhost:8080/test.html 就无法通过ajax直接获取 http://google.com 的数据。

例如,我用ajax去访问一个不同域的页面,错误结果是这样的:

大家想想,这样其实也有道理。如果没有同源策略,你我都可以随便通过ajax直接获取其他网站的信息,这还不乱套了。。。我自己做一个搜索界面,搜索时直接用ajax从百度获取数据,那不成了小偷了。。。

但是跨域访问是少不了的,mail.163.com 的网页可能需要从 news.163.com 域下获取新闻信息,那怎么办?——开始咱们的跨域之旅。(当然用iframe也可以实现)

从“盗链”说起

互联网的许多网站之间图片相互盗链,A网站网页的img.src直接链接到B网站的图片地址,这是常有的事儿。说到“盗链”,大家第一想到的可能是如何去防止盗链,今儿咱不管那个。

你再想想“盗链”和“同源策略”这两个词之间有什么关系?——对,矛盾!既然都“同源策略”了,怎么还能“盗链”呢?

世间万物都有矛盾,有矛盾了照样可以和谐共处,并不一定非要你死我活。

重点:<img>src(获取图片),<link>href(获取css),<script>src(获取javascript)这三个都不符合同源策略,它们可以跨域获取数据。因此,你可以直接从一些cdn上获取jQuery,并且你网站上的图片也随时可能被别人盗用,所有最好加上水印!

而我们今天的主角——jsonp——就是因为<script>的src不符合同源策略而来的。

JSONP

例如,域名 a.com 下有一个 a.com/test.html 网页,域名 b.com 下有一个 b.com/data.html 网页和 b.com/alert.js 文件。

引导第一步:简单引用js

编写 b.com/alert.js 如下:

alert(123);

对 a.com/test.html 编写如下代码:

<script type='text/javascript' src='http://b.com/alert.js'/>

运行 a.com/test.html,结果很明显,就是弹出123

引导第二步:引用js返回数据

将 b.com/alert.js 修改为:

myFn(100);

将 a.com/test.html 修改为:

<script>
function myFn ( data ) {
alert( data + 'px' );
}
</script>
<script type='text/javascript' src='http://b.com/alert.js'/>

运行 a.com/test.html,结果是弹出100px,这个应该也没有什么疑问。

引导第三步:已经跨域成功!

第二步中,如果data——即100——是我要跨域在b.com下获取的一个数据,那么咱们这不就是已经实现跨域请求了吗!!!

把这个过程再清晰的捋一遍:

  • <script>src不符合同源策略;
  • 我通过给<script>src赋值一个跨域的文件的网址(可能不是一个js文件),这个文件返回的字符串,浏览器会当作javascript来解析;
  • 而这段javascript中,就可以包含着我所需要的跨域服务器端的数据;
  • 最后,我在本页面定义一个myFn函数用来展示数据,而这段javascript中就可以直接调用myFn函数;

引导第四步:引用html格式

<script>src不一定仅仅指向javascript文件,可以指向任何地址。例如:
将 a.com/test.html 修改为:

<script>
function myFn ( data ) {
alert( data + 'px' );
}
</script>
<script type='text/javascript' src='http://b.com/data.html'/>

将 b.com/data.html 编写为:(注意,data.html中就写以下一行代码,多了不写)

myFn(100);

运行 a.com/test.html ,结果依然是100px,其中,100就是我们要跨域请求的数据。

引导第五步:动态数据

如果要请求的数据是动态的,那就要在动态页面中编写。那么我们就让 a.com/test.html 去调用一个动态的aspx页面:

<script>
function myFn ( data ) {
alert( data + 'px' );
}
</script>
<script type='text/javascript' src='http://b.com/data.aspx?callback=myFn'/>

大家注意,我们在 src 地址中增加了?callback=myFn,意思是把显示数据的函数也动态传过去了,而第二步、第四步都是静态的写在被调用的文件中的。至于callback参数后台如何接收,如何使用,请接着看:
在 b.com 下增加一个 b.com/data.aspx 页面,后台代码如下:

    protected void Page_Load(object sender, EventArgs e)
{
if (this.IsPostBack == false)
{
string callback = "";
if (Request["callback"] != null)
{
callback = Request["callback"]; //服务器端要返回的数据
string data = "1024"; Response.Write(callback + "(" + data + ")");
}
}
}

代码很简单,获取callback参数,然后组成一个函数的形式返回。如果b.com/data.aspx?callback=myFn调用的话,那么返回的就是myFn(1024)

返回的数据变成动态的了(“1024”),前端页面用于显示数据的函数也编程了动态的了(“callback=myFn”),但是归根结底,形式还是一样的。

引导第六步:调用封装

a.com/test.html 中,仅仅有一个<script>静静的躺在那里,执行一次之后,就没有作用了。

而实际情况是,a.com/test.html 中,可能随着用户的操作发生若干次的调用。怎么办?——动态增加呗。

function addScriptTag(src) {
var script = document.createElement("script");
script.setAttribute("type", "text/javascript");
script.src = src;
document.body.appendChild(script);
} function myFn (data) {
alert(data + 'px');
} //需要调用时:
//addScriptTag('b.com/data.aspx?callback=myFn');

总结

以上层层描述的就是JSONP,你不必去记住它的定义,看明白了上述文字,就全能理解。

重点在于:同源策略 + <script>src不属于同源策略 + 通过<script>的src指向的文件返回服务器端数据。

ok,就这些!

JSONP - 从理论到实践的更多相关文章

  1. 【C#代码实战】群蚁算法理论与实践全攻略——旅行商等路径优化问题的新方法

    若干年前读研的时候,学院有一个教授,专门做群蚁算法的,很厉害,偶尔了解了一点点.感觉也是生物智能的一个体现,和遗传算法.神经网络有异曲同工之妙.只不过当时没有实际需求学习,所以没去研究.最近有一个这样 ...

  2. Java 理论与实践: 处理 InterruptedException

    捕捉到它,然后怎么处理它? 很多 Java™ 语言方法,例如 Thread.sleep() 和 Object.wait(),都可以抛出InterruptedException.您不能忽略这个异常,因为 ...

  3. Java 理论与实践: 非阻塞算法简介——看吧,没有锁定!(转载)

    简介: Java™ 5.0 第一次让使用 Java 语言开发非阻塞算法成为可能,java.util.concurrent 包充分地利用了这个功能.非阻塞算法属于并发算法,它们可以安全地派生它们的线程, ...

  4. Java 理论与实践: 流行的原子——新原子类是 java.util.concurrent 的隐藏精华(转载)

    简介: 在 JDK 5.0 之前,如果不使用本机代码,就不能用 Java 语言编写无等待.无锁定的算法.在 java.util.concurrent 中添加原子变量类之后,这种情况发生了变化.请跟随并 ...

  5. Java 理论和实践: 了解泛型

    转载自 : http://www.ibm.com/developerworks/cn/java/j-jtp01255.html 表面上看起来,无论语法还是应用的环境(比如容器类),泛型类型(或者泛型) ...

  6. Java 理论与实践: 处理 InterruptedException(转)

    很多 Java™ 语言方法,例如 Thread.sleep() 和 Object.wait(),都可以抛出InterruptedException.您不能忽略这个异常,因为它是一个检查异常(check ...

  7. DDD(领域驱动设计)理论结合实践

    DDD(领域驱动设计)理论结合实践   写在前面 插一句:本人超爱落网-<平凡的世界>这一期,分享给大家. 阅读目录: 关于DDD 前期分析 框架搭建 代码实现 开源-发布 后记 第一次听 ...

  8. Java 理论与实践: 并发集合类

    Java 理论与实践: 并发集合类 DougLea的 util.concurrent 包除了包含许多其他有用的并发构造块之外,还包含了一些主要集合类型 List 和 Map 的高性能的.线程安全的实现 ...

  9. 浅读《视觉SLAM十四讲:从理论到实践》--操作1--初识SLAM

    下载<视觉SLAM十四讲:从理论到实践>源码:https://github.com/gaoxiang12/slambook 第二讲:初识SLAM 2.4.2 Hello SLAM(书本P2 ...

随机推荐

  1. 使用swiper 轮播插件ajax 请求加载图片时,无法滑动问题

    因为图片是动态创建的,在插件开始初始化时,文档流中没用图片,故没有创建相应宽度.通过调整js加载顺序,问题还是没有解决. 最后找到swiper插件 api 有属性是可以根据内容变动,自动初始化插件的, ...

  2. 浅谈脚本化css(三)之方块运动函数

    我们可以写一个让小方块运动的函数: div#demo { width: 100px; ; position: absolute; ; ; } var div = document.getElement ...

  3. Wampserver环境配置

    ☆根目录修改问题 /.修改运行根目录 1.修改apache配置,将服务请求定位到新目录下 →左击wampserver,点击Apache打开httpd.conf文件,Ctrl+f搜索documentro ...

  4. JavaWeb学习总结(十):Session简单使用

    一.Session简单介绍 在WEB开发中,服务器可以为每个用户浏览器创建一个会话对象(session对象),注意:一个浏览器独占一个session对象(默认情况下).因此,在需要保存用户数据时,服务 ...

  5. html-图像标签

    图像标签 <img src="图片的路径"/> -src:图片的路径 -width:图片的宽度 -height:图片的高度 -alt:图片上显示的文字,把鼠标移动到图片 ...

  6. map与pagelayout同步新方法

    本文转自: http://hi.baidu.com/murphy1314/blog/item/3d3144f319b19dcf0a46e0a4.html 前天写的那个MapControl和Pagela ...

  7. CSS3 选择器用法小结

    表单选择器: /*:enabled 可用的 :disabled 被禁用的 :focus 获取了焦点的 多用在表单元素上*/ input:enabled {...} input:disabled {.. ...

  8. eclipse maven构建的java web工程项目 在修改了工程项目名时,tomcat启动异常java.lang.IllegalArgumentException: Can't convert argument:null

    问题 我修改了前一个项目的名称.重新启动该项目至tomcat,报错:Java.lang.IllegalArgumentException: Can't convert argument: null 因 ...

  9. ASP.NET中母版页引用外部js或css文件无效,提示对象未定义解决方法

    最近做网站用了一个js+css实现的带有二级菜单的导航条,在母版页创建好后,子页面调用出现了许多奇怪的问题,多方查证后的最终解决方案和大家分享下.... 1.路径问题 如果是一个单独的aspx页面调用 ...

  10. Tomcat性能监控之Probe

    目前采用java进行开发的系统居多,这些系统运行在java容器中,通过对容器的监控可以了解到java进程的运行状况,分析java程序问题.目前市面上流行的中间件有很多(Tomcat.jetty.jbo ...