AJAX跨域实战

简介:

本文目的

今天终于梳理清楚了AJAX跨站请求的原理和解决方案,在此记录下,作为备忘。

 

浏览器同源策略

同源策略又名同域策略是浏览器中的主要安全措施。这里的“源”指的是主机名协议端口号的组合;我们可以把一个“源”看作是某个web页面或浏览器所浏览的信息的创建者。 同源策略,简单地说就是要求动态内容(例如,JavaScript或者VBScript)只能阅读与之同源的那些HTTP应答和cookies,而不能阅读来自不同源的内容。更为有趣的是,同源策略对写操作没有任何限制。因而,一个web站点可以向任何其他的Web站点发送(或写入)HTTP请求,尽管为 了防止跨站请求可能会对发送这些请求有关的cookies和头部有所限制。(以上描述来之网络

通俗的讲:同源策略就浏览器不允许是站点A的js脚本访问站点B提供的动态数据,因为这样可能带来安全隐患

 

 

如何跨域

跨域就是绕过同源策略限制,使得站点A的js脚本可以访问到站点B提供的数据。怎么绕过呢?比较常见跨域方案是使用代理,即在A站点下搭建一个代理(可以是个自己的CGI),让代理访问B站点,并将结果反给A页面,这种方法的可扩展性不够好,实施成本大。目前比较经典的方案使用JSONP方式(json with padding)。从上面的定义中,可以知道浏览器不允许A的js脚本访问B提供的数据,但是没有阻止拉取B站点提供的静态资源,如js文件,图片等。所以,跨域的关键在于如何利用好这些“静态”的内容。举个例子:

A站点需要访问B站点的数据,B站点有下面的脚本(PHP编写的cgi):

1
2
3
<?php
echo json_encode(array(‘msg’=>’cross domain access’));
?>

这样是无法拿到数据的,因为B站点吐出的是json数据,如下:

1
{“msg”:”cross domain access”}

但如果将B站点的脚本改成下面的样子,站点A就可以访问到数据。

1
2
3
<?php
echo ‘localFunc(’. json_encode(array(‘msg’=>’cross domain access’)). ‘);’;
?>

因为此时,返回的结果如下:

1
localFunc({“msg”:”cross domain access”});

没错,是一个函数调用,可以理解为脚本,而不是数据,浏览器认为合法,所以允许访问。当然,localFunc函数需要在A站点的页面定义。

 

 

script标签跨域

上面描述了原理,接下来描述具体如何实时。首先,我们需要搭建两个站点,我的实验环境是LAMP,所以在apache中设置了两个virtual host: http://a.oa.comhttp://b.oa.com

搭建好后,将文件index.html拷贝到站点A根目录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<! DOCTYPE  html>
< html >
     <!--A站点首页 index.html-->
     < head >
         < meta  http-equiv="Content-Type" content="text/html; charset=UTF-8">
         < script  type="text/javascript" src="http://code.jquery.com/jquery-1.8.1.min.js "></ script >
         < title >cross domain demo</ title >
     </ head >
     < body >
         < input  type="button" value="JSONP跨站原理" onclick="onClickCrossJSONPTheory();"></ input >< br />
         < input  type="button" value="JSONP跨站jquery简化后版本" onclick="onClickCrossJSONP();"></ input >< br />
         < input  type="button" value="getScript跨站" onclick="onClickJQueryScript();"></ input >< br />
     </ body >
     < script >
         function localFunc(data) {
             alert(data.msg);
         }
         function onClickCrossJSONPTheory() {
             var script = document.createElement("script");
             script.type = "text/javascript";
             script.src = "http://b.oa.com/index.php?callback=localFunc";
             document.getElementsByTagName('head')[0].appendChild(script);
             // 省略删除
         }
         function onClickCrossJSONP() {
             $.getJSON('http://b.oa.com/index.php?callback=?', function(json) {
                 alert(json.msg);
             });
         }
         function onClickJQueryScript() {
             $.getScript('http://b.oa.com/alert.js', function(){
                 cross();
                 cross();
             });
         }
     </ script >
</ html >

将index.php文件拷贝到B站点根目录

1
2
3
4
<?php
// B站点首页: index.php
echo  $_GET [ 'callback' ] . '('  . json_encode( array ( 'msg' => 'hello cross-domain' )) . ');' ;
?>

为A站点和B站点配上host(很重要),打开浏览器,输入“http://a.oa.com”,得到如下页面:

clip_image002

点击第一个按纽会弹出对话框,答应站点B的内容,如下:

clip_image004

我们看看index.html中都做了些什么:

1. 定义回调函数localFunc

2. 在onClickCrossJSONPTheory函数中动态加载script标签

3. 将localFunc作为url参数

4. 清理创建的标签(省略),如果不清理,script标签会越来越多。

而B站点将传过来的回调函数包装上(padding)自己的数据(JSON),返回给A站点。

这么简单,就“骗”过了浏览器,不是吗?

 

 

$.getJSON跨域

上面的步骤是不是有点麻烦,除了自定义函数需要根据不同业务逻辑而变化,其他步骤全部都是一样,所以这些基本上可以提取出来重用。

好在jquery提供了这样的机制。点击页面上的第二个按钮,实现了同样的功能,但是用了3行代码(onClickCrossJSONP函数中的实现),其他的工作jquery帮我们做了。我们只需要在$.getJSON的url参数中添加一个回调参数,值用问号“”代替,如下:

clip_image006

这样jquery框架会自动填充一个唯一的函数名称,也就是后面匿名回调函数的名称,http抓包显示如下:

clip_image008

 

 

$.getScript跨域

最后,捎带说明一下$.getScript函数,用法与getJSON类似,只不过它可以直接和js文件交互,而不是cgi,列子如上,需要在B站点根目录下添加alert.js文件,如下:

1
2
3
4
5
6
7
// 定义函数
function  cross() {
     alert( 'cross domain execute' );
}
 
// 调用函数
cross();

点击A站点首页的第三个按钮,可以发现弹出了三次对话框,说明getScript加载js后,会执行它,然后回调函数的中也可以调用相关函数和对象。

 

总结

  1. 浏览器同源策略是基于安全的考虑强制执行
  2. 跨域方法:1)代理; 2)JSONP两种方式进行跨域操作(推荐)
  3. jquery框架的$.getJSON可以简化JSONP的实现过程
  4. JSONP需要CGI做出调整,返回的数据必须是js代码(函数调用),而不是json数据。

 

参考资料

声明:如有转载本博文章,请注明出处。您的支持是我的动力!文章部分内容来自互联网,本人不负任何法律责任。
本文转自bourneli博客园博客,原文链接:http://www.cnblogs.com/bourneli/archive/2012/09/12/2682116.html ,如需转载请自行联系原作者
相关文章
|
6月前
|
设计模式 前端开发 JavaScript
Ajax技术【Ajax 实战】(二)-全面详解(学习总结---从入门到深化)
Ajax技术【Ajax 实战】(二)-全面详解(学习总结---从入门到深化)
49 0
|
6月前
|
JSON 前端开发 Java
利用Spring Boot处理JSON数据实战(包括jQuery,html,ajax)附源码 超详细
利用Spring Boot处理JSON数据实战(包括jQuery,html,ajax)附源码 超详细
132 0
|
JSON 前端开发 JavaScript
前端AJAX入门到实战,学习前端框架前必会的(ajax+node.js+webpack+git)(一)
前端AJAX入门到实战,学习前端框架前必会的(ajax+node.js+webpack+git)(一)
585 0
|
2月前
|
前端开发
React技术栈-react使用的Ajax请求库实战案例
这篇文章介绍了在React应用中使用Axios和Fetch库进行Ajax请求的实战案例,展示了如何通过这些库发送GET和POST请求,并处理响应和错误。
43 10
React技术栈-react使用的Ajax请求库实战案例
|
4月前
|
前端开发 API 开发者
Python Web开发者必看!AJAX、Fetch API实战技巧,让前后端交互如丝般顺滑!
【7月更文挑战第13天】在Web开发中,AJAX和Fetch API是实现页面无刷新数据交换的关键。在Flask博客系统中,通过创建获取评论的GET路由,我们可以展示使用AJAX和Fetch API的前端实现。AJAX通过XMLHttpRequest发送请求,处理响应并在成功时更新DOM。Fetch API则使用Promise简化异步操作,代码更现代。这两个工具都能实现不刷新页面查看评论,Fetch API的语法更简洁,错误处理更直观。掌握这些技巧能提升Python Web项目的用户体验和开发效率。
57 7
|
5月前
|
前端开发 Python
Django框架中Ajax GET与POST请求的实战应用
Django框架中Ajax GET与POST请求的实战应用
|
4月前
|
前端开发 JavaScript API
js【详解】ajax (含XMLHttpRequest、 同源策略、跨域、JSONP)
js【详解】ajax (含XMLHttpRequest、 同源策略、跨域、JSONP)
48 0
|
5月前
|
前端开发 JavaScript 安全
详尽分享突破ajax不能跨域的限制
详尽分享突破ajax不能跨域的限制
32 0
|
6月前
|
移动开发 前端开发 安全
Ajax跨域的所有方法(最详细带使用教程!!!)
Ajax跨域的所有方法(最详细带使用教程!!!)
|
6月前
|
设计模式 缓存 前端开发
Ajax技术【Ajax 实战】(二)-全面详解(学习总结---从入门到深化)(下)
Ajax技术【Ajax 实战】(二)-全面详解(学习总结---从入门到深化)
43 1