前两天被问到ajax跨域如何解决,还真被问住了,光知道有个什么jsonp,迷迷糊糊的没有说上来。抱着有问题必须解决的态度,我看了许多资料,原来如此。。。

为何一直知道jsonp,但一直迷迷糊糊的不明白呢?——网上那些介绍资料都写的太复杂了!

我是能多简单就多简单,争取让你十分钟看完!

1. 同源策略

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

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

http://google.com  和  https://google.com 不同,因为协议不同;

http://localhost:8080  和  http://localhost:1000 不同,因为端口不同;

http://localhost:8080  和  https://google.com 不同,协议、域名、端口号都不同,根本不是一家的。

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

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

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

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

2. 从“盗链”说起

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

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

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

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

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

3. 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');

4. 总结

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

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

ok,就这些!

---------------

引用自:http://www.cnblogs.com/wangfupeng1988/p/4060747.html

【JS跨域请求】Ajax跨域请求JSONP的更多相关文章

  1. session跨域和ajax跨域名

    后台跨域和ajax跨域名: 后台跨域: www.baidu.com   主域名(一级域名一般以www开头) news.baidu.com   二级域名 (a.test.com和b.test.com有相 ...

  2. JS跨域(ajax跨域、iframe跨域)解决方法及原理详解(jsonp)

    这里说的js跨域是指通过js在不同的域之间进行数据传输或通信,比如用ajax向一个不同的域请求数据,或者通过js获取页面中不同域的框架中(iframe)的数据.只要协议.域名.端口有任何一个不同,都被 ...

  3. 【转】JS跨域(ajax跨域、iframe跨域)解决方法及原理详解(jsonp)

    这里说的js跨域是指通过js在不同的域之间进行数据传输或通信,比如用ajax向一个不同的域请求数据,或者通过js获取页面中不同域的框架中(iframe)的数据.只要协议.域名.端口有任何一个不同,都被 ...

  4. Ajax跨域请求附带Cookie/Ajax跨域请求附带身份凭证

    一.跨域请求中默认不带cookie等验证凭证 尤其对于post请求. 对于ajax请求,其中post,get都可以正常访问. withCredentials: false, // 允许携带cookie ...

  5. Ajax跨域:Jsonp原理解析

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

  6. Ajax跨域访问解决办法

    方法1. jsonp实现ajax跨域访问示例 jsp代码: <body> <input type="button" onclick="testJsonp ...

  7. Ajax 跨域,这应该是最全的解决方案了

    https://segmentfault.com/a/1190000012469713 前言 从刚接触前端开发起,跨域这个词就一直以很高的频率在身边重复出现,一直到现在,已经调试过N个跨域相关的问题了 ...

  8. 细说Ajax跨域

    一.什么是跨域 跨域问题来自于浏览器同源策略的限制,包括DOM同源限制和Ajax同源限制,本文探讨的是Ajax跨域.Ajax跨域指的是一个页面的Ajax只能请求和当前页面同源的数据,如果发现请求到的数 ...

  9. ajax跨域,这应该是最全的解决方案了

    前言 从刚接触前端开发起,跨域这个词就一直以很高的频率在身边重复出现,一直到现在,已经调试过N个跨域相关的问题了,16年时也整理过一篇相关文章,但是感觉还是差了点什么,于是现在重新梳理了一下. 个人见 ...

  10. ajax 跨域----好用的解决方案

    一.前言 跨域这个词就一直以很高的频率在身边重复出现,一直到现在,已经调试过N个跨域相关的问题了! 但是感觉还是差了点什么,于是现在重新梳理了一下.个人见识有限,如有差错,请多多见谅 二.前言 关于跨 ...

随机推荐

  1. JDBC标准事物编程模式

    事物简介: 事物是一种数据库中保证交易可靠的机制,JDBC支持数据库中事物的概念,默认情况下事物是默认提交的. 事物的特性: 1.事物必须是原子工作单元,对于其数据的修改,要么都执行,要么都不执行2. ...

  2. hdoj 1089(费马小定理)

    题目大意:方程f(x)=5*x^13+13*x^5+k*a*x:输入任意一个数k,是否存在一个数a,对任意x都能使得f(x)能被65整出. 现假设存在这个数a ,因为对于任意x方程都成立 所以,当x= ...

  3. c++primerplus(第六版)编程题——第3章(数据类型)

    声明:作者为了调试方便,每一章的程序写在一个工程文件中,每一道编程练习题新建一个独立文件,在主函数中调用,我建议同我一样的初学者可以采用这种方式,调试起来会比较方便. 工程命名和文件命名可以命名成易识 ...

  4. mysqldump: command not found问题解决

    首先得知道mysql命令或mysqldump命令的完整路径,可以使用find命令查找除非你知道mysql安装路径可以略过这一步. find / -name mysql -print 例如我的mysql ...

  5. opencv之图像膨胀

    #include <cv.h> #include <highgui.h> void main() { IplImage* src; IplImage*dst; src=cvLo ...

  6. 关于Unity导出的Android应用在小米、联想等机型上崩溃的问题

    应用在三星手机上运行没有出现问题,但在小米和联想手机上会崩溃.这个问题在刚开始时一直查不到问题所在,后来发现是因为Android清单文件中声明的权限出现了重复,去掉了重复的权限之后,就没有出现崩溃的情 ...

  7. 首页重定位到mian.action上

    <body onload="top.location.href='<%=request.getContextPath()%>/main.action';">

  8. shell命令记录一些

    ps aux | sort -k 5n|tail -5 找到内存最对的进程 ps  aux 是找出全部的进程 sort -k 5n 表示第5个参数进行排序 tail -5 表示最后5个 ps -e - ...

  9. BZOJ 1024 生日快乐

    Description windy的生日到了,为了庆祝生日,他的朋友们帮他买了一个边长分别为 X 和 Y 的矩形蛋糕.现在包括windy,一共有 N 个人来分这块大蛋糕,要求每个人必须获得相同面积的蛋 ...

  10. TransactionScope IsolationLevel 事务隔离级别

    事务有四个特性 第一原子性,事务具有独立的不能被拆分的,不能只做部分,事务的性质是要么全做,要么都不做. 第二统一性,在事务执行之前和事务执行之后的数据是一致. 第三隔离性,事务是独立的,开发者不能查 ...