Javascript几种跨域方式总结
在客户端编程语言中如javascript,同源策略规定跨域之间的脚本是隔离的,一个域的脚本不能访问和操作另外一个域的绝大部分属性和方法。只有当两个域具有相同的协议,相同的主机,相同的端口时,我们就认定他们是相同的域。可是在实际开发中我们经常需要获取其他域的资源,这个时候各种不同的跨域资源方式就各显神通了,今天主要来总结一下工作中常用的几种跨域方式,以备查询。
1.window.name
window 对象的name属性是一个很特别的属性,当在 frame 中加载新页面时,name 的属性值依旧保持不变。那么我们可以在页面 A中用iframe加载其他域的页面B,而页面B中用JavaScript把需要传递的数据赋值给window.name,iframe加载完成之后,此时 name 属性值可被获取到,以访问 Web 服务发送的信息。但 name 属性仅对相同域名的 frame 可访问。这意味着为了访问 name 属性,当远程 Web 服务页面被加载后,必须导航 frame 回到原始域。即页面A修改iframe的地址,将其变成同域的一个地址,然后就可以读出window.name的值了。一旦 name 属性获得,销毁 frame 。这个方式非常适合单向的数据请求,而且协议简单、安全。
页面B(www.jesse.com/data.html)代码如下:
<script type="text/javascript">
window.name = 'I was there!';
// 这里是要传输的数据,大小一般为2M,IE和firefox下可以大至32M左右
// 数据格式可以自定义,如json、字符串
</script>
页面A(www.jack.com/index.html)代码如下:
<script type="text/javascript">
var state = 0,
iframe = document.createElement('iframe'),
loadfn = function() {
if (state === 1) {
var data = iframe.contentWindow.name; // 读取数据
console.log(data); //弹出'I wasthere!'
(function(){
//获取数据以后销毁这个iframe。
iframe.contentWindow.document.write('');
iframe.contentWindow.close();
document.body.removeChild(iframe);
})();
} else if (state === 0) {
state = 1;
// 设置的代理页面使其回原始域
iframe.contentWindow.location = "http://www.jack.com/proxy.html";
}
};
iframe.src = 'http://www.jesse.com/data.html';
if (iframe.attachEvent) {
iframe.attachEvent('onload', loadfn);
} else {
iframe.onload = loadfn;
}
document.body.appendChild(iframe);
</script>
2.具备src的标签
虽然浏览器默认禁止了跨域访问,但并不禁止在页面中用标签的src属性引用其他域的文件。根据这一点,可以方便地通过创建具有src属性的节点方法来实现完全跨域的通信。使用这种原理的跨域方式有以下几种:
动态创建script
例如我要从域A的页面pageA加载域B的数据,那么在域B的页面pageB中我以JavaScript的形式声明pageA需要的数据,然后在 pageA中用script标签把pageB加载进来,那么pageB中的脚本就会得以执行。
pageA(www.jack.com/index.html)代码如下:
function getData(data){
//这里是对获取的数据的相关操作
console.log(data);
//数据获取到后移除创建的script标签
document.body.removeChild(originData);
}
var originData = document.createElement('script');
originData.src = 'http://www.jesse.com/data.js';
originData.setAttribute("type", "text/javascript");
document.body.appendChild(originData);
pageB(www.jesse.com/data.js)代码如下:
getData('这里是远程跨域获取的数据');//数据格式可以自定义,如json、字符串
jsonp
在用$.ajax()获取远程数据时,如果是跨域资源则可以使用jsonp方法,以前一直以为jsonp是ajax的一种,后来才明白他们根本就不是一回事。ajax是以xhr方式请求数据的,而jsonp是以script方式请求数据的,这个就是和上面的动态创建script方式一样。
pageA(www.jack.com/index.html)代码如下:
$.ajax({
//JSONP不支持POST方式
type:"GET",
url:"http://www.jesse.com/data.php",
dataType:"jsonp",
//自定义的jsonp回调函数名称,默认为jQuery自动生成的随机函数名,也可以写"?",jQuery会自动为你处理数据
jsonpCallback:"getData",
success: function(data){
console.log(data);
},
error: function(){
console.log('fail');
}
})
pageB(www.jesse.com/data.js)代码如下:
<?php
$callback = $_GET['callback'];//得到回调函数名,这里是getData
$data = array('a','b','c');//要返回的数据
echo $callback.'('.json_encode($data).')';//输出
?>
3.document.domain
对于主域相同而子域不同的例子,可以通过设置document.domain的办法来解决。 具体的做法是可以在http://www.a.com/a.html和http://script.a.com/b.html两个文件中分别加上 document.domain = "a.com";然后通过a.html文件中创建一个iframe,去控制iframe的contentDocument,这样两个js文件之间就可以 “交互”了。当然这种办法只能解决主域相同而二级域名不同的情况
www.a.com上的a.html
document.domain = 'a.com';
var ifr = document.createElement('iframe');
ifr.src = 'http://script.a.com/b.html';
ifr.style.display = 'none';
document.body.appendChild(ifr);
ifr.onload = function(){
var doc = ifr.contentDocument || ifr.contentWindow.document;
// 在这里操纵b.html
alert(doc.getElementsByTagName("h1")[0].childNodes[0].nodeValue);
};
script.a.com上的b.html
document.domain = 'a.com';
4.跨域资源共享(CORS)
原理:跨源资源共享(CORS)定义一种跨域访问的机制,可以让AJAX实现跨域访问。CORS允许一个域上的网络应用向另一个域提交跨域AJAX请求。实现此功能非常简单,只需由服务器发送一个响应标头即可。它是通过客户端+服务端协作声明的方式来确保请求安全的。服务端会在HTTP请求头中增加一系列HTTP请求参数(例如Access-Control-Allow-Origin等),来限制哪些域的请求和哪些请求类型可以接受,而客户端在发起请求时必须声明自己的源(Orgin),否则服务器将不予处理,如果客户端不作声明,请求甚至会被浏览器直接拦截都到不了服务端。服务端收到HTTP请求后会进行域的比较,只有同域的请求才会处理。
pageA(www.jack.com/index.html)代码如下:
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(){
if(xhr.readyState === 4 && xhr.status === 200){
console.log(xhr.responseText);
}
};
xhr.open("get","http://www.jesse.com/data.php");
xhr.send(null);
pageB(www.jesse.com/data.php)代码如下:
<?php
header("Access-Control-Allow-Origin: http://www.jack.com");//与简单的请求相同
header("Access-Control-Allow-Methods: GET, POST");//允许请求的方法
header("Access-Control-Max-Age: 3628800"); //将这个请求缓存多长时间
$data = array('a','b','c');//要返回的数据
echo json_encode($data);//输出
?>
5.window.postMesage 不常用
window.postMessage(message,targetOrigin) 方法是html5新引进的特性,可以使用它来向其它的window对象发送消息,无论这个window对象是属于同源或不同源,目前IE8+、FireFox、Chrome、Opera等浏览器都已经支持window.postMessage方法。
pageA(www.jack.com/index.html)代码如下:
<iframe id="proxy" src="http://www.jesse.com/index.html" onload="postMsg()" style="display: none"></iframe>
<script type="text/javascript">
var obj = {
msg: 'hello world'
}
function postMsg() {
var iframe = document.getElementById('proxy');
var win = iframe.contentWindow;
win.postMessage(obj, 'http://www.jesse.com');
}
</script>
pageB(www.jesse.com/data.php)代码如下:
<script type="text/javascript">
window.onmessage = function(e) {
console.log(e.data.msg + " from " + e.origin);
}
</script>
6. location.hash 不常用
pageA(www.jack.com/index.html)代码如下:
function startRequest() {
var ifr = document.createElement('iframe');
ifr.style.display = 'none';
ifr.src = 'http://www.jesse.com/b.html#sayHi'; //传递的location.hash
document.body.appendChild(ifr);
}
function checkHash() {
try {
var data = location.hash ? location.hash.substring(1) : '';
if (console.log) {
console.log('Now the data is ' + data);
}
} catch (e) {};
}
setInterval(checkHash, 5000);
window.onload = startRequest;
pageA(www.jack.com/proxy.html)代码如下:
parent.parent.location.hash = self.location.hash.substring(1);
pageB(www.jesse.com/b.html)代码如下:
function checkHash() {
var data = '';
//模拟一个简单的参数处理操作
switch (location.hash) {
case '#sayHello':
data = 'HelloWorld';
break;
case '#sayHi':
data = 'HiWorld';
break;
default:
break;
}
data && callBack('#' + data);
}
function callBack(hash) {
// ie、chrome的安全机制无法修改parent.location.hash,所以要利用一个中间的www.a.com域下的代理iframe
var proxy = document.createElement('iframe');
proxy.style.display = 'none';
proxy.src = 'http://www.jack/c.html' + hash; // 注意该文件在"www.jack.com"域下
document.body.appendChild(proxy);
}
window.onload = checkHash;
参考文章:
Javascript几种跨域方式总结的更多相关文章
- 从壹开始前后端分离【 .NET Core2.0 +Vue2.0 】框架之十二 || 三种跨域方式比较,DTOs(数据传输对象)初探
更新反馈 1.博友@落幕残情童鞋说到了,Nginx反向代理实现跨域,因为我目前还没有使用到,给忽略了,这次记录下,为下次补充.此坑已填 2.提示:跨域的姊妹篇——<三十三║ ⅖ 种方法实现完美跨 ...
- JSONP和CORS两种跨域方式的简单介绍和解决方案实例
随着软件开发分工趋于精细,前后端开发分离成为趋势,前端同事负责前端页面的展示及页面逻辑处理,服务端同事负责业务逻辑处理同时通过API为前端提供数据也为前端提供数据的持久化能力,考虑到前后端同事开发工具 ...
- JSONP和CORS两种跨域方式的优缺点及使用方法原理介绍
随着软件开发分工趋于精细,前后端开发分离成为趋势,前端同事负责前端页面的展示及页面逻辑处理,服务端同事负责业务逻辑处理同时通过API为前端提供数据也为前端提供数据的持久化能力,考虑到前后端同事开发工具 ...
- 「JavaScript」四种跨域方式详解
超详细并且带 Demo 的 JavaScript 跨域指南来了! 本文基于你了解 JavaScript 的同源策略,并且了解使用跨域跨域的理由. 1. JSONP 首先要介绍的跨域方法必然是 JSON ...
- 「JavaScript」JS四种跨域方式详解
原文地址https://segmentfault.com/a/1190000003642057 超详细并且带 Demo 的 JavaScript 跨域指南来了! 本文基于你了解 JavaScript ...
- jsonp的三种跨域方式
1.通过jq的$.ajax()完成跨域,这是我比较喜欢的一种方式. 代码如下: $.ajax({ type:'get', async:true, url:'地址', dataType:'jsonp', ...
- java web 的 几种跨域方式
- JavaScript最全的10种跨域共享的方法
在客户端编程语言中,如javascript和ActionScript,同源策略是一个很重要的安全理念,它在保证数据的安全性方面有着重要的意义.同源策略规定跨域之间的脚本是隔离的,一个域的脚本不能访问和 ...
- JavaScript中的跨域
跨域是什么 跨域就是指从一个域名的网页去请求另一个域名的资源,因为JavaScript同源策略的限制,资源无法获取.比如从www.baidu.com 页面去请求 www.google.com 的资源, ...
随机推荐
- iOS 之 Property List
1. 概念 用于存储串行化对象,xml格式,存储到plist文件中. 2. 用途 存储用户设置. 3. 优点 程序运行时可动态创建和读写. 4. 使用说明 4.1. 获取plist文件 NSStrin ...
- 【angularjs】【学习心得】ng-class总结
原文:http://www.imooc.com/wenda/detail/236998 今天来说一点angularjs中看起来很简单但是实践起来又有不少问题的ng-class吧 ----------- ...
- 利用PHPCMS V9站群功能建立分站
hosts文件就在C:\Windows\system32\drivers\etc\hosts下 用一套CMS软件系统,做多个网站,统一管理,用户可以互通,这就是所谓的站群功能.这对于运营和维护都能节省 ...
- RMAN中FILESPERSET设置对备份速度的影响
看到网上部分人说不指定FILESPERSET(默认值=64)则会导致分配的通道只走第一个而导致备份效率低下,今天仔细研究了一下,参照了多个博主文章,得出结论如下: 如果没有指定filesperset, ...
- Windows Server 2008 R2防火墙入站规则
一般服务器的端口都设置了外网无法访问,iis中创建的网站外网也是访问不了的,需要创建指定端口的入站规则后方可访问. 方法/步骤 服务器管理器-->配置-->高级安全windows防 ...
- Apache的.htaccess到Nginx的转换
今天项目要求从Apache转到Nginx,遇到了要将原来的rewrite规则移过来的问题,找了半天资源,居然有一个转换工具,地址如下: http://www.anilcetin.com/convert ...
- 如何改变xls中的单元格左上角的图标
点绿色小三角的是文本型数字,是不能参与加减运算的.首先选中含有绿色小三角的单元格,右击鼠标选择,设置单元格格式, 数字选项卡,选择常规
- JSP 初始化参数
JSP 初始化参数: tomcat启动的时候就会执行那个函数: xml: <?xml version="1.0" encoding="UTF-8"?> ...
- 搭建Minisipserve服务器实现局域网内IOS客户端idoubs的通信
idoubs是IOS设备开发的第一款全功能并开放源码的3GPP IMS客户端,它同时专为IOS平台开发设计的voIP测试版客户端,以doubango为框架,能实现当前最先进的多媒体功能,主要功能有:语 ...
- java连接ms sql server各类问题解析
首先先来说下使用微软自己开发的架包进行ms sql server数据库的连接时,sql 2000与sql 2005的连接方式略有不同: 1.首先驱动不一样,sql 2000的连接驱动包有三个,分别是: ...