javascript中jsonp用法及跨域实例

Asynchronous JavaScript and XML(Ajax)是目前 Web 开发关键技术之一,允许客户端 JavaScript 通过 HTTP 与服务器进行交互。

浏览器的安全模型规定了 XMLHttpRequest、frames 等必须在相同域名下才能进行通信。这就是所谓的“同源策略限制”。

为了 Web 应用的安全,同源策略并不是坏东西,但当我们真的需要请求其他域名下的数据时,这个策略确实造成了麻烦。

克服该限制的方法:

1、还是请求自己的服务器,让服务器做代理,把请求转发给真正的第三方服务器。这个方案的使用比较普遍,但一看上去就挺浪费的。

2、Flash。服务器上要部署一个 crossdomain.xml 文件,并将功能在 Flash 中开发,以达到跨域目的。但是要学习 AS 开发语言,成本较高。

3、通过 <script src=""> 标签,进行脚本插入。标签中的脚本源指向第三方服务器,因为同源策略并不阻止标签中引进第三方服务器的脚本。通过 JSON 可以改进该方案。缺点在于:难调试、被不信任的服务使用时会存在危险。

JSONP 属于第 3 种方案。

JSONP(JSON with Padding)是一个非官方的协议,他的实现方式简单,但需要一点服务端的配合。大致就是:让客户端决定要回调的 Javascript 函数名,在第三方服务端将 JSON 数据拼装到回调函数名中,返回的就是参数为 JSON 数据的函数调用脚本,浏览器加载脚本,并执行,达到获取第三方数据的目的。下面是最初级的实现代码。

客户端代码:

<script type="text/javascript">
function jsonpCallback(result) {
alert(result.a);
alert(result.b);
alert(result.c);
for(var i in result) {
alert(i+":"+result[i]); //循环输出a:1,b:2,etc.
}
}
</script>
<script type="text/javascript" src="http://crossdomain.com/services.php?callback=jsonpCallback"></script>

服务端 services.php 代码:

<?php
//服务端返回JSON数据
$data = array('a'=>1,'b'=>2,'c'=>3,'d'=>4,'e'=>5);
$result = json_encode($data);

$callback = $_GET['callback'];
echo $callback . "(" . $result . ")"; //动态执行回调函数

jQuery中的 $.getJSON $.ajax $.get 也有用到 JSONP,不知道大家注意到没。

同源策略

首先基于安全的原因,浏览器是存在同源策略这个机制的,同源策略阻止从一个源加载的文档或脚本获取或设置另一个源加载的文档的属性。看起来不知道什么意思,实践一下就知道了。

1. 随便建两个网页

在你的apache的httpd.conf配置文件中添加如下配置:

Apache

Listen 11111
Listen 22222
 
namevirtualhost localhost:11111
namevirtualhost localhost:22222
 
<VirtualHost  localhost:11111>
ServerAdmin   tangrucheng@gmail.com
ServerName   localhost:11111
DocumentRoot   E:/wamp/www/test/test11111
</VirtualHost>
 
<Directory   "E:/wamp/www/test/test11111">
Options   Indexes   FollowSymLinks MultiViews
AllowOverride   All
Order   allow,deny
Allow   from   all
</Directory>
 
<VirtualHost  localhost:22222>
ServerAdmin   tangrucheng@gmail.com
ServerName   localhost:22222
DocumentRoot   E:/wamp/www/test/test22222
</VirtualHost>
 
<Directory   "E:/wamp/www/test/test22222">
Options   Indexes   FollowSymLinks
AllowOverride   None
Order   allow,deny
Allow   from   all
</Directory>
这样一个端口是11111,一个22222,按照定义它们是不同源的

 2. 用jQuery发起不同源的请求

在11111端口的网页上添加一个按钮,Click事件随便发起向端口为22222域的请求:

 

<html>
<head>
    <title>11111</title>
</head>
<body>
    <button id="get22222">Click</button>
 
    <script src="http://ajax.aspnetcdn.com/ajax/jquery/jquery-1.8.0.js" type="text/javascript"></script>
    <script type="text/javascript">
        $("#get22222").click(function () {
            $.get("http://localhost:22222/js/jquery.min.js", function (data) {
                console.log(data)
            })
 
            $.get("http://localhost:22222/index.php", function (data) {
                console.log(data)
            })
        })
    </script>
</body>
</html>

根据同源策略,很明显会悲剧了。浏览器会阻止,根本不会发起这个请求。

OK,原来jsonp是要解决这个问题的。

 

script标签的跨域能力

不知道大家知不知道CDN这个东西,例如微软的CDN,使用它,我们的网页可以不提供jQuery,由微软的网站帮我们提供:

XHTML

<script src="http://ajax.aspnetcdn.com/ajax/jquery/jquery-1.8.0.js" type="text/javascript"></script>

回到我们的11111端口的网页,上面我们在Click事件里有一个对22222端口域的jQuery文件的请求,这次使用script标签来请求。

XHTML

<script type="text/javascript" src="http://localhost:22222/js/jquery.min.js"></script>
当然,200,OK了。

 

同样是端口11111的网页发起对22222域的请求,放在script里设置scr属性的OK了,另一个方式就悲剧。利用script的跨域能力,这就是jsonp的基础。

 利用script获取不同源的json

既然它叫jsonp,很明显目的还是json,而且是跨域获取。根据上面的分析,很容易想到:利用js构造一个script标签,把json的url赋给script的scr属性,把这个script插入到dom里,让浏览器去获取。实践

E:\wamp\www\test\test11111\index.phpPHP
<html>
<head>
    <title>11111</title>
</head>
<body>
    <button id="get22222">Click</button>
 
    <script src="http://ajax.aspnetcdn.com/ajax/jquery/jquery-1.8.0.js" type="text/javascript"></script>
    <script type="text/javascript">
        function CreateScript(src) {
            $("<script><//script>").attr("src", src).appendTo("body")
        }
        $("#get22222").click(function () {
            CreateScript("http://localhost:22222/index.php");
        })
    </script>
</body>
</html>

E:\wamp\www\test\test22222\index.phpPHP

 
<?php
 
$arr = array ('a'=>1,'b'=>2,'c'=>3,'d'=>4,'e'=>5);
 
echo json_encode($arr);

 

首先,第一个浏览器,http://localhost:22222/index.php这个Url的确是存在一个json的,而且在端口11111网页上用script标签来请求这个22222这个Url也是200OK的,但是最下面报js语法错误了。原来用script标签加载完后,会立即把响应当js去执行,很明显{"a":1,"b":2,"c":3,"d":4,"e":5}不是合法的js语句。

 

利用script获取异域的jsonp

显然,把上面的json放到一个回调方法里是最简单的方法。例如,变成这样:

E:\wamp\www\test\test22222\index.phpPHP

<?php
 
$callback = $_GET['callback'];
 
$arr = array ('a'=>1,'b'=>2,'c'=>3,'d'=>4,'e'=>5);
 
echo $callback . '(' . json_encode($arr) . ')';

如果存在jsonpcallback这个方法,那么jsonpcallback({"a":1,"b":2,"c":3,"d":4,"e":5})就是合法的js语句。

由于服务器不知道客户端的回调是什么,不可能hard code成jsonpcallback,所以就带一个QueryString让客户端告诉服务端,回调方法是什么,当然,QueryString的key要遵从服务端的约定,上面的是”callback“。

添加回调函数:

JavaScript

function jsonpcallback(json) {
  console.log(json)
}

把前面的方法稍微改改参数:

JavaScript

$("#get22222").click(function () {
  CreateScript("http://localhost:22222/index.php?callback=jsonpcallback");
})

200OK,服务器返回jsonpcallback({"a":1,"b":2,"c":3,"d":4,"e":5}),我们也写了jsonpcallback方法,当然会执行。OK顺利获得了json。没错,到这里就是jsonp的全部。

 

利用jQuery获取jsonp

上面的方式中,又要插入script标签,又要定义一个回调,略显麻烦,利用jQuery可以直接得到想要的json数据,同样是上面的jsonp(服务器端代码不变):

E:\wamp\www\test\test11111\index.phpXHTML

<html>
<head>
    <title>11111</title>
</head>
<body>
    <button id="get22222">Click</button>
 
    <script src="http://ajax.aspnetcdn.com/ajax/jquery/jquery-1.8.0.js" type="text/javascript"></script>
    <script type="text/javascript">
        $("#get22222").click(function () {
            $.ajax({
                url: 'http://localhost:22222/index.php',
                dataType: "jsonp",
                jsonp: "callback",
                success: function (data) {
                    console.log(data)
                }
            })
        })
    </script>
</body>
</html>

得到的结果跟上面一样。
 

总结

一句话就是利用script标签绕过同源策略,获得一个类似这样的数据,jsonpcallback是页面存在的回调方法,参数就是想得到的json。

JavaScript

jsonpcallback({"a":1,"b":2,"c":3,"d":4,"e":5})

到这里不免产生一个疑惑,同源策略是基于安全的原因建立的,发起不同源的请求是被认为不安全的,不可以接受的,但为什么这样绕一个小圈子就可以接受呢?这样就安全了吗?感觉就像洗澡时怕被人看见,把门关上,但侧面的大窗户却是打开的,这样做有意义吗?元芳你怎么看?

时间: 2024-09-20 15:25:22

javascript中jsonp用法及跨域实例的相关文章

php cookie用法与跨域实例教程

/*  语法:   setcookie(name,value,expire,path,domain,secure)  name,cookie名称 必填  value, cookie值,必写    其它的可写,不过来说明一来功能  expire 过期时间如: time()+3600*24  path 路径如:/根目录,也可以指定二级目录如 /111cn.net/  domain 域名,这个就是做了二级域名是要注明了,如果我你让所有二级域都可以访问这个cookie的话就如这样设置:".111cn.n

Javascript中innerHTML用法实例分析

 这篇文章主要介绍了Javascript中innerHTML用法,实例分析了实用innerHTML获取对应元素内容的使用技巧,需要的朋友可以参考下     本文实例讲述了Javascript中innerHTML用法.分享给大家供大家参考. 具体实现方法如下:   代码如下: <html> <head> <script type="text/javascript"> function t(){ var cont = document.getElemen

Javascript中arguments用法实例分析_javascript技巧

本文实例讲述了Javascript中arguments用法.分享给大家供大家参考.具体分析如下: 先来看如下示例: function add(n1,n2){ return n1+n2; } function add(n1,n2,n3) { return n1+n2+n3; } alert(add(1,2)); //NaN,js中调用方法采用就近原则: //而由于该方法没有传入n3,所以结果是NaN js中没有方法重载,怎么解决上面这个问题? //arguments function f1(){

javascript中AJAX用法实例分析_javascript技巧

本文实例讲述了javascript中AJAX用法.分享给大家供大家参考.具体分析如下: 兼容地获得XMLHttpRequest对象: var xhr = null; if(window.XMLHttpRequest){ //非IE浏览器 xhr = window.XMLHttpRequest; }else if(window.ActiveXObject){ //IE浏览器 try{ //高版本,受msxml3.dll+支持 xhr = new ActiveXObject("Msxml2.XMLH

Javascript中innerHTML用法实例分析_javascript技巧

本文实例讲述了Javascript中innerHTML用法.分享给大家供大家参考. 具体实现方法如下: 复制代码 代码如下: <html> <head> <script type="text/javascript"> function t(){  var cont = document.getElementById('container');  var htmlcode = "<p>哈哈哈哈</p>";  

javascript中attachEvent用法实例分析_javascript技巧

本文实例讲述了javascript中attachEvent用法.分享给大家供大家参考.具体分析如下: 一般我们在JS中添加事件,是这样子的 obj.onclick=method 这种绑定事件的方式,兼容主流浏览器,但如果一个元素上添加多次同一事件呢? obj.onclick=method1 obj.onclick=method2 obj.onclick=method3 如果这样写,那么只有最后绑定的事件,这里是method3会被执行,这个时候我们就不能用onclick这样的写法了,主角改登场了,

Javascript中Array用法实例分析_javascript技巧

本文实例讲述了Javascript中Array用法.分享给大家供大家参考.具体分析如下: JavaScript中的Array对象就是数组,首先是一个动态数组,而且是一个像C#.Java中"数组.List.HashMap/Dictionary"等的超强综合体. Array数组 使用方式: 例1: var citys = new Array(); //创建数组对象,无需初始化长度,动态 citys[0] = '上海'; citys[1] ='北京'; citys[2] = '深圳'; fo

深入浅析Jsonp解决ajax跨域问题

一.介绍 最近跨域问题比较多,而且自己刚好也看到这一块,就总结了一下,关于JSONP的东西百度的话东西确实很多,很多人都是复制别人的,如此下去,其实找的资料就那么几份,关键是我还看不懂,可能是能力问题吧,自己经过很多尝试,所以总结了一下,终究还是弄懂了皮毛.注意一点是,这里是用Jsonp解决ajax的跨域问题,具体的实现其实不是ajax. 1.同源策略 浏览器有一个很重要的概念--同源策略(Same-Origin Policy).所谓同源是指,域名,协议,端口相同.不同源的客户端脚本(JavaS

用jQuery与JSONP轻松解决跨域访问的问题_jquery

时间过得好快,又被拉回js战场时, 跨域问题这个伤疤又开疼了. 好在,有jquery帮忙,跨域问题似乎没那么难缠了.这次也借此机会对跨域问题来给刨根问底,结合实际的开发项目,查阅了相关资料,算是解决了跨域问题..有必要记下来备忘. 跨域的安全限制都是指浏览器端来说的.服务器端是不存在跨域安全限制的,所以通过本机服务器端通过类似httpclient方式完成"跨域访问"的工作,然后在浏览器端用AJAX获取本机服务器端"跨域访问"对应的url.来间接完成跨域访问也是可以的