当前位置: 首页 > 编程日记 > 正文

JavaScript跨域总结与解决办法

JavaScript跨域总结与解决办法

  • 什么是跨域
  • 1、document.domain+iframe的设置
  • 2、动态创建script
  • 3、利用iframe和location.hash
  • 4、window.name实现的跨域数据传输
  • 5、使用HTML5 postMessage
  • 6、利用flash

本文来自网络(http://f2e.me/200904/cross-scripting/,该网址已不能访问),仅作个人读书笔记之用,并稍作修改和补充。

什么是跨域

JavaScript出于安全方面的考虑,不允许跨域调用其他页面的对象。但在安全限制的同时也给注入iframe或是ajax应用上带来了不少麻烦。这里把涉及到跨域的一些问题简单地整理一下:

首先什么是跨域,简单地理解就是因为JavaScript同源策略的限制,a.com 域名下的js无法操作b.com或是c.a.com域名下的对象。更详细的说明可以看下表:

URL说明是否允许通信
http://www.a.com/a.js
http://www.a.com/b.js
同一域名下允许
http://www.a.com/lab/a.js
http://www.a.com/script/b.js
同一域名下不同文件夹允许
http://www.a.com:8000/a.js
http://www.a.com/b.js
同一域名,不同端口不允许
http://www.a.com/a.js
https://www.a.com/b.js
同一域名,不同协议不允许
http://www.a.com/a.js
http://70.32.92.74/b.js
域名和域名对应ip不允许
http://www.a.com/a.js
http://script.a.com/b.js
主域相同,子域不同不允许
http://www.a.com/a.js
http://a.com/b.js
同一域名,不同二级域名(同上)不允许(cookie这种情况下也不允许访问)
http://www.cnblogs.com/a.js
http://www.a.com/b.js
不同域名不允许
特别注意两点:
第一,如果是协议和端口造成的跨域问题“前台”是无能为力的,
第二:在跨域问题上,域仅仅是通过“URL的首部”来识别而不会去尝试判断相同的ip地址对应着两个域或两个域是否在同一个ip上。
“URL的首部”指window.location.protocol +window.location.host,也可以理解为“Domains, protocols and ports must match”。

接下来简单地总结一下在“前台”一般处理跨域的办法,后台proxy这种方案牵涉到后台配置,这里就不阐述了,有兴趣的可以看看yahoo的这篇文章:《JavaScript: Use a Web Proxy for Cross-Domain XMLHttpRequest Calls》

1、document.domain+iframe的设置

对于主域相同而子域不同的例子,可以通过设置document.domain的办法来解决。具体的做法是可以在http://www.a.com/a.html和http://script.a.com/b.html两个文件中分别加上document.domain = ‘a.com’;然后通过a.html文件中创建一个iframe,去控制iframe的contentDocument,这样两个js文件之间就可以“交互”了。当然这种办法只能解决主域相同而二级域名不同的情况,如果你异想天开的把script.a.com的domian设为alibaba.com那显然是会报错地!代码如下:

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';

这种方式适用于{www.kuqin.com, kuqin.com, script.kuqin.com, css.kuqin.com}中的任何页面相互通信。

备注:某一页面的domain默认等于window.location.hostname。主域名是不带www的域名,例如a.com,主域名前面带前缀的通常都为二级域名或多级域名,例如www.a.com其实是二级域名。 domain只能设置为主域名,不可以在b.a.com中将domain设置为c.a.com。

问题:
1、安全性,当一个站点(b.a.com)被攻击后,另一个站点(c.a.com)会引起安全漏洞。
2、如果一个页面中引入多个iframe,要想能够操作所有iframe,必须都得设置相同domain。

2、动态创建script

虽然浏览器默认禁止了跨域访问,但并不禁止在页面中引用其他域的JS文件,并可以自由执行引入的JS文件中的function(包括操作cookie、Dom等等)。根据这一点,可以方便地通过创建script节点的方法来实现完全跨域的通信。具体的做法可以参考YUI的Get Utility

这里判断script节点加载完毕还是蛮有意思的:ie只能通过script的readystatechange属性,其它浏览器是script的load事件。以下是部分判断script加载完毕的方法。

js.onload = js.onreadystatechange = function() {
if (!this.readyState || this.readyState === 'loaded' || this.readyState === 'complete') {
// callback在此处执行
js.onload = js.onreadystatechange = null;
}
};

3、利用iframe和location.hash

这个办法比较绕,但是可以解决完全跨域情况下的脚步置换问题。原理是利用location.hash来进行传值。在url: http://a.com#helloword中的‘#helloworld’就是location.hash,改变hash并不会导致页面刷新,所以可以利用hash值来进行数据传递,当然数据容量是有限的。假设域名a.com下的文件cs1.html要和cnblogs.com域名下的cs2.html传递信息,cs1.html首先创建自动创建一个隐藏的iframe,iframe的src指向cnblogs.com域名下的cs2.html页面,这时的hash值可以做参数传递用。cs2.html响应请求后再将通过修改cs1.html的hash值来传递数据(由于两个页面不在同一个域下IE、Chrome不允许修改parent.location.hash的值,所以要借助于a.com域名下的一个代理iframe;Firefox可以修改)。同时在cs1.html上加一个定时器,隔一段时间来判断location.hash的值有没有变化,一点有变化则获取获取hash值。代码如下:

先是a.com下的文件cs1.html文件:

function startRequest(){
var ifr = document.createElement('iframe');
ifr.style.display = 'none';
ifr.src = 'http://www.cnblogs.com/lab/cscript/cs2.html#paramdo';
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, 2000);

cnblogs.com域名下的cs2.html:

//模拟一个简单的参数处理操作
switch(location.hash){
case '#paramdo':
callBack();
break;
case '#paramset':
//do something……
break;
}
function callBack(){
try {
parent.location.hash = 'somedata';
} catch (e) {
// ie、chrome的安全机制无法修改parent.location.hash,
// 所以要利用一个中间的cnblogs域下的代理iframe
var ifrproxy = document.createElement('iframe');
ifrproxy.style.display = 'none';
ifrproxy.src = 'http://a.com/test/cscript/cs3.html#somedata';    // 注意该文件在"a.com"域下
document.body.appendChild(ifrproxy);
}
}

a.com下的域名cs3.html

//因为parent.parent和自身属于同一个域,所以可以改变其location.hash的值
parent.parent.location.hash = self.location.hash.substring(1);

当然这样做也存在很多缺点,诸如数据直接暴露在了url中,数据容量和类型都有限等……

4、window.name实现的跨域数据传输

文章较长列在此处不便于阅读,详细请看 window.name实现的跨域数据传输。

5、使用HTML5 postMessage

HTML5中最酷的新功能之一就是 跨文档消息传输Cross Document Messaging。下一代浏览器都将支持这个功能:Chrome 2.0+、Internet Explorer 8.0+, Firefox 3.0+, Opera 9.6+, 和 Safari 4.0+ 。 Facebook已经使用了这个功能,用postMessage支持基于web的实时消息传递。

otherWindow.postMessage(message, targetOrigin);
otherWindow: 对接收信息页面的window的引用。可以是页面中iframe的contentWindow属性;window.open的返回值;通过name或下标从window.frames取到的值。
message: 所要发送的数据,string类型。
targetOrigin: 用于限制otherWindow,“*”表示不作限制

a.com/index.html中的代码:

<iframe id="ifr" src="b.com/index.html"></iframe>
<script type="text/javascript">
window.onload = function() {
var ifr = document.getElementById('ifr');
var targetOrigin = 'http://b.com';  // 若写成'http://b.com/c/proxy.html'效果一样
// 若写成'http://c.com'就不会执行postMessage了
ifr.contentWindow.postMessage('I was there!', targetOrigin);
};
</script>

b.com/index.html中的代码:

<script type="text/javascript">
window.addEventListener('message', function(event){
// 通过origin属性判断消息来源地址
if (event.origin == 'http://a.com') {
alert(event.data);    // 弹出"I was there!"
alert(event.source);  // 对a.com、index.html中window对象的引用
// 但由于同源策略,这里event.source不可以访问window对象
}
}, false);
</script>

参考文章:《精通HTML5编程》第五章——跨文档消息机制、https://developer.mozilla.org/en/dom/window.postmessage

6、利用flash

这是从YUI3的IO组件中看到的办法,具体可见http://developer.yahoo.com/yui/3/io/。
可以看在Adobe Developer Connection看到更多的跨域代理文件规范:ross-Domain Policy File Specifications、HTTP Headers Blacklist。

原文出处:http://www.cnblogs.com/rainman/archive/2011/02/20/1959325.html

相关文章:

这几个 Python 的小技巧,你会么?

来源丨Python小二作者 Peter Gleeson 是一名数据科学家&#xff0c;日常工作几乎离不 python。一路走来&#xff0c;他积累了不少有用的技巧和 tips&#xff0c;现在就将这些技巧分享给大家。这些技巧将根据其首字母按 A-Z 的顺序进行展示。ALL OR ANYPython 之所以成为这么一门…

如何创建可扩展表视图中的iOS 学习和拓展优化(有待更新)

首先介绍老外的文章&#xff1a;《How To Create an Expandable Table View in iOS》这是老外用Swift实现的&#xff0c;对应的老外github项目源码&#xff1a;https://github.com/appcoda/expandable-table-view小编经过学习了老外的Expandable Table View然后用Objective-C实…

String、StringBuffer、StringBuilder的理解

问题: 理解 Java的字符串&#xff0c;String、StringBuffer、StringBuilder 有什么区别&#xff1f; 知识点 字符串设计和实现考量 String是Immutable(线程安全、字符串常量池复用)。Immutable对象在拷贝时候不需要额外复制数据。至于为什么imumutable&#xff0c;源码如下&…

Linux(centos6.0)下安装Node.js以及使用

Linux下(centos6.0)安装Node.js1.wget http://nodejs.org/dist/node-v0.6.9.tar.gz tar zxvf node-v0.6.9.tar.gz cd node-v0.6.9 ./configure --prefix/usr/local/node ----------安装提示-------------Checking for program g or c : not found Checking for progr…

Pandas 中的这些函数/属性将被 deprecated

作者 | luanhz来源丨小数志导读Pandas对于日常数据分析和处理来说是最常用的工具&#xff08;没有之一&#xff09;&#xff0c;笔者之前也总结分享了很多相关用法和技巧。与之不同&#xff0c;今天本文来介绍几个已经在函数文档中列入"deprecated"的函数/属性&#…

2016.01.04 论文改重

今天的任务是修改查重的问题&#xff0c;另外加入参考文献。 其中&#xff0c;上午的时间完成论文查重。 下午的时间完成参考文献的丰富和标记。 晚上的时间完成DOM基础&#xff08;李炎恢&#xff09;的学习 预计晚上八点到晚上十点 优先级&#xff1a;论文查重&#xff0c;参…

完美数据迁移-MongoDB Stream的应用

目录 一、背景介绍二、常见方案1. 停机迁移2. 业务双写3. 增量迁移三、Change Stream 介绍监听的目标变更事件四、实现增量迁移五、后续优化小结附参考文档一、背景介绍 最近微服务架构火的不行&#xff0c;但本质上也只是风口上的一个热点词汇。 作为笔者的经验来说&#xff0…

Tslib移植与分析【转】

转自&#xff1a;http://blog.csdn.net/water_cow/article/details/7215308 目标平台&#xff1a;LOONGSON-1B开发板&#xff08;mips32指令集&#xff09;编译平台&#xff1a;x86PC--VMware6.5--Ubuntu10.04&#xff08;下面简称“ubuntu系统”&#xff09; 或&am…

用 Python 写一个天天酷跑,在线摸鱼不烦恼

来源丨Python小二写出来的效果图就是这样了&#xff1a;下面就更新一下全部的代码吧~还是老样子先定义import pygame,sys import random写一下游戏配置width 1200 #窗口宽度 height 508 #窗口高度 size width, height scoreNone #分数…

php fsockopen解决办法

最近研究php多线程的问题&#xff0c;发现中文资源少的可怜&#xff0c;仅有的几篇文章被转了又转&#xff0c;但文中内容价值有限。搜索过程中发现国外很多网站引用的一篇文章写的不错&#xff0c;所以翻译过来。版权声明&#xff1a;可以任意转载&#xff0c;转载时请务必以超…

深入浅出JVM的锁优化案例

锁优化适应性自旋&#xff08;Adaptive Spinning&#xff09;线程阻塞的时候&#xff0c;让等待的线程不放弃cpu执行时间&#xff0c;而是执行一个自旋(一般是空循环)&#xff0c;这叫做自旋锁。自旋等待本身虽然避免了线程切换的开销&#xff0c;但它是要占用处理器时间的&…

DOMContentLoaded 与onload区别以及使用

一、何时触发这两个事件&#xff1f; 1、当 onload 事件触发时&#xff0c;页面上所有的DOM&#xff0c;样式表&#xff0c;脚本&#xff0c;图片&#xff0c;flash都已经加载完成了。 2、当 DOMContentLoaded 事件触发时&#xff0c;仅当DOM加载完成&#xff0c;不包括样式表&…

php-fpm – 配置详解

http://duyongguang.blogbus.com/logs/156375484.html php5.3自带php-fpm /usr/local/php/etc/php-fpm.conf pid run/php-fpm.pidpid设置&#xff0c;默认在安装目录中的var/run/php-fpm.pid&#xff0c;建议开启 error_log log/php-fpm.log错误日志&#xff0c;默认在安装目…

真香!Vision Transformer 快速实现 Mnist 识别

作者 | 李秋键出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09;引言&#xff1a;基于深度学习的方法在计算机视觉领域中最典型的应用就是卷积神经网络CNN。CNN中的数据表示方式是分层的&#xff0c;高层特征表示依赖于底层特征&#xff0c;由浅入深抽象地提取高级特征…

(二十一)数组的初始化

class Demo3 {public static void main(String[] args) {//数组的初始化int[] a new int[] {12,13,14,15};int[] b {12,13,14,15};//数组的便利for(int i 0;i<4;i) {System.out.println(a[i]);}for(int i 0;i<b.length;i) {System.out.println(b[i]);}} }转载于:http…

深入探讨PHP中的内存管理问题

一、 内存在PHP中&#xff0c;填充一个字符串变量相当简单&#xff0c;这只需要一个语句"&#xff1c;?php $str hello world ; ?&#xff1e;"即可&#xff0c;并且该字符串能够被自由地修改、拷贝和移动。而在C语言中&#xff0c;尽管你能够编写例如"char …

介绍一个效率爆表的数据采集框架

作者 | 俊欣来源丨关于数据分析与可视化今天我们来聊一下如何用协程来进行数据的抓取&#xff0c;协程又称为是微线程&#xff0c;也被称为是用户级线程&#xff0c;在单线程的情况下完成多任务&#xff0c;多个任务按照一定顺序交替执行。那么aiohttp模块在Python中作为异步的…

最多显示6行并且最多显示三条文本

为什么80%的码农都做不了架构师&#xff1f;>>> private void setCommentContent(ViewHolder vh, String feedId, int commentNum, ArrayList<CommentItem> comment_lists){if(commentNum < 0 || comment_lists null || comment_lists.isEmpty()){for(in…

【刷算法】LeetCode- 两数之和

题目描述 给定一个整数数组和一个目标值&#xff0c;找出数组中和为目标值的两个数。 你可以假设每个输入只对应一种答案&#xff0c;且同样的元素不能被重复利用。 示例: 给定 nums [2, 7, 11, 15], target 9因为 nums[0] nums[1] 2 7 9 所以返回 [0, 1] 复制代码分析 第…

栈区和堆区内存分配区别

一直以来总是对这个问题的认识比较朦胧&#xff0c;我相信很多朋友也是这样的&#xff0c;总是听到内存一会在栈上分配&#xff0c;一会又在堆上分配&#xff0c;那么它们之间到底是怎么的区别呢&#xff1f;为了说明这个问题&#xff0c;我们先来看一下内存内部的组织情况&…

高精度进制转换

高精度进制转换&#xff1a; 对于普通的不是非常大的数的相互转换&#xff0c;我们一般採用不断模取余的方法&#xff0c;比如&#xff1a;将10进制数m转换成n进制数&#xff0c;则对m模n取余就可以。可是&#xff0c;假设是一个有几百、几千或者很多其它位的大数呢&#xff1f…

远程办公,你希望在家工作几天?

受疫情影响&#xff0c;员工的工作方式不得不发生改变。在过去短短的几个月内&#xff0c;远程办公从偶然一次变成了常态化。随着疫情的反复&#xff0c;远程办公再次成为了许多企业的选择。3月份携程正式启动了“32”混合办公模式&#xff0c;即每周有1-2天&#xff0c;员工可…

python爬虫日志(9)爬取代理

2019独角兽企业重金招聘Python工程师标准>>> 话不多说&#xff0c;直接上代码&#xff0c;很简单&#xff0c;很容易看懂 import requests from bs4 import BeautifulSoup import randomdef get_ip_list():print("正在获取代理列表...")ip_url http://ww…

使php支持mbstring库以及使用

1.执行yum install php-mbstring2. 修改php.ini (这一步非常重要, 部分lxadmin版本无法自动修改)echo ‘extensionmbstring.so’ >>/etc/php.ini #更具php安装目录而定3. 重启web service如果是apache: service httpd restart方法二&#xff1a;php 5.36安装目录&#xf…

仿余额宝数字跳动效果 TextCounter

1、TextCounter 效果 2、TextCounter 说明 每次打开余额宝第一件事情就去看看有多少钱&#xff0c;最炫的就是看着钱在跳动相当的舒服&#xff0c;今天放出这个效果。 温馨提示&#xff1a;支持的Android版本最低的是Android 4.0.0 IceCreamSandwich &#xff08; API等级14 &a…

年仅 16 岁的黑客少年,竟是搅乱 IT 巨头的幕后主使?

整理 | 郑丽媛出品 | CSDN近来&#xff0c;黑客组织 Lapsus$ 活跃在各大科技网站&#xff1a;窃取英伟达近 1TB 的数据、泄露三星近 190GB 的机密数据、公布微软 Bing 和 Cortana 源码…不同于大部分黑客组织&#xff0c;Lapsus$ 没有刻意隐藏自己&#xff0c;反而行事非常高调…

使用硬盘,安装双系统,Win7+CentOS

我用那个U盘装了很多次都不行&#xff0c;都是说找不到文件。最后就找了一篇博客看如何安装双系统&#xff0c;最后发现原来可以用硬盘安装的。经过5个多小时终于完成了。^-^。 1.首先是分区&#xff0c;可以使用Window7自带的磁盘管理程序进行分区。&#xff08;PS 我是用Cent…

Linux 文件系统剖析

Linux 文件系统剖析 按照分层结构讨论 Linux 文件系统 M. Tim Jones, 顾问工程师, Emulex Corp. 简介&#xff1a; 在文件系统方面&#xff0c;Linux 可以算得上操作系统中的 “瑞士军刀”。Linux 支持许多种文件系统&#xff0c;从日志型 文件系统到集群文件系统和加密文件系统…

Docker构建Nginx+Tomcat动静分离架构

随着主流Nginx WEB服务器的发展&#xff0c;现在基于Nginx的WEB服务器已广泛应用于各大互联网企业。今天我们来使用docker构建我们的LinuxNginxTomcat动静分离服务器。1) 启动docker镜像查看当前系统存在的镜像&#xff0c;我这里为CentOS6.6&#xff0c;大家可以参考我第一…

硬核!Python 四种变量的代码对象和反汇编分析

作者 | 大奎整理 | 阳哥来源丨Python数据之道在Python基础的学习过程中&#xff0c;对变量和参数的理解有助于我们从更基础层面了解Python语言的运行。在这个过程中&#xff0c;还是有不少冷门和细节的地方需要进一步熟悉。今天我们来分享Python四种变量的代码对象和反汇编分析…