浏览器安全的基石是“同源政策”(same-origin policy)。

1995年,同源政策由 Netscape 公司引入浏览器。目前,所有浏览器都实行这个政策。

何为同源?

  • 协议相同
  • 域名相同
  • 端口相同

限制范围

  • Cookie、LocalStorage 和 IndexedDB 无法读取。
  • DOM 无法获得。
  • AJAX 请求不能发送。

  PS:Form表单提交不受同源政策限制;

一级域名相同,二级域名不同网页Cookie 和 iframe规避同源政策

一级域名相同,只是二级域名不相同的2个网页(A页和B页)间通信(共享cookie和ifrmame DOM):

//A网页通过脚本设置一个 Cookie
document.cookie = "test1=hello"; //B网页不能读取
var allCookie = document.cookie; //父窗口不能读取子iframe的DOM对象,报错
document.getElementById("myIFrame").contentWindow.document //同样子窗口不能获取父窗口的元素,报错
window.parent.document.body

如果两个窗口一级域名相同,只是二级域名不同,那么设置document.domain属性,就可以规避同源政策,共享cookie和获取DOM,解决上面的问题:

//设置为一级域名,规避同源政策
document.domain = 'example.com';

完全不同源网站解决跨域窗口间通信问题

有2种方法:

  • 片段识别符(fragment identifier)
  • 跨文档通信API(Cross-document messaging)

片段识别符(fragment identifier),指的是URL的#号后面的部分,将此作为两个窗口通信内容的中介存储,可互为读取,实现通信。

父窗口把信息写入子窗口的片段识别符:

var src = originURL + '#' + data;
document.getElementById('myIFrame').src = src;

子窗口通过监听hashchange事件,得到通知:

window.onhashchange = checkMessage;

function checkMessage() {
var message = window.location.hash;
// ...
}

同样,子窗口也可以改变父窗口的片段识别符:

parent.location.href= target + “#” + hash;

上面两种方法都属于破解,HTML5为了解决这个问题,引入了一个全新的API:跨文档通信 API(Cross-document messaging)。

这个API为window对象新增了一个window.postMessage方法,允许跨窗口通信,不论这两个窗口是否同源:

父窗口向子窗口发送消息:

var popup = window.open('http://bbb.com', 'title');
popup.postMessage('Hello World!', 'http://bbb.com');

子窗口向父窗口发送消息:

window.opener.postMessage('Nice to see you', 'http://aaa.com');

postMessage方法的第一个参数是具体的信息内容,第二个参数是接收消息的窗口的源(origin),即“协议 + 域名 + 端口”。也可以设为*,表示不限制域名,向所有窗口发送。

父窗口或子窗口监听对方发来的消息:

window.addEventListener('message', function(e) {
console.log(e.data);
},false);

message事件的事件对象提供3个属性:

  • event.source:发送消息的窗口
  • event.origin: 消息发向的网址
  • event.data: 消息内容

子窗口通过event.source属性引用父窗口,然后回复消息:

window.addEventListener('message', receiveMessage);
function receiveMessage(event) {
event.source.postMessage('Nice to see you!', '*');
}

event.origin属性可以过滤不是发给本窗口的消息:

window.addEventListener('message', receiveMessage);
function receiveMessage(event) {
if (event.origin !== 'http://aaa.com') return;
if (event.data === 'Hello World') {
event.source.postMessage('Hello', event.origin);
} else {
console.log(event.data);
}
}

一个跨文档通信API案例:

//父窗口发送消息的代码
var win = document.getElementsByTagName('iframe')[].contentWindow;
var obj = { name: 'Jack' };
win.postMessage(JSON.stringify({key: 'storage', data: obj}), 'http://bbb.com'); //子窗口接收消息,写入localStorage
window.onmessage = function(e) {
if (e.origin !== 'http://bbb.com') {
return;
}
var payload = JSON.parse(e.data);
localStorage.setItem(payload.key, JSON.stringify(payload.data));
};

AJAX与同源政策

同源政策规定,AJAX请求只能发给同源的网址,否则就报错。

AJAX有3种方法规避同源政策:

  • JSONP
  • WebSocket
  • CORS

第1种:JSONP

JSONP是服务器与客户端跨源通信的常用方法。最大特点就是简单适用,老式浏览器全部支持,服务器改造非常小。

它的基本思想是,网页通过添加一个<script>元素,向服务器请求JSON数据,这种做法不受同源政策限制;服务器收到请求后,将数据以一个指定名字的回调函数的参数形式传回客户端,客户端在约定名字的回调函数中处理接收到的参数 。

首先,网页动态插入<script>元素,由它向跨源网址发出请求。

function addScriptTag(src) {
var script = document.createElement('script');
script.setAttribute("type","text/javascript");
script.src = src;
document.body.appendChild(script);
} window.onload = function () {
addScriptTag('http://example.com/ip?callback=foo');
} function foo(data) {
console.log('Your public IP address is: ' + data.ip);
};

服务器收到这个请求以后,会将数据放在回调函数的参数位置返回:

foo({
"ip": "8.8.8.8"
});

由于<script>元素请求的脚本,直接作为代码运行。这时,只要浏览器定义了foo函数,该函数就会立即调用。作为参数的JSON数据被视为JavaScript对象,而不是字符串,所以不用JSON.parse处理,直接作为JSON对象使用。

参考

同源政策,阮一峰 http://javascript.ruanyifeng.com/bom/same-origin.html

浏览器-同源政策(same-origin policy)的更多相关文章

  1. 破解浏览器同源政策利器之JSONP

    本文是在了解了浏览器的同源规则之后,学习了破解这个规则的一个简单有效的方法->JSONP.主要通过阮一峰老师的博客学习 浏览器的同源规则 有这样一个背景,如果你通过银行的网站进行的取钱的交易,而 ...

  2. 前端开发必须说的那些事之——同源策略(same origin policy)

    同源策略指的是三个相同 协议相同 域名相同 端口相同 如https://www.baidu.com/hahah.html这个网址来说 https是使用的协议,www.baidu.com是域名,端口号默 ...

  3. 为什么ajax 必须同源,same origin policy

    ajax 所有请求都会附带主域的cookie, 若没有同源策略,攻击者就可以获取你的cookie,状态.

  4. Same Origin Policy 浏览器同源策略详解

    同源策略 Same Origin Policy 日常开发中最常与网络打交道,那关于浏览器的同源策略和跨域相关的知识是该整理一下了. 首先需要明确的是,同源策略是浏览器的安全策略,由于存在这个策略,我们 ...

  5. [js]浏览器同源策略(same-origin policy)

    浏览器的同源策略 浏览器同源政策及其规避方法 什么是同源策略 A网页设置的 Cookie,B网页不能打开,除非这两个网页"同源".所谓"同源"指的是" ...

  6. 同源策略(same-origin policy)及三种跨域方法

    同源策略(same-origin policy)及三种跨域方法 1.同源策略 含义: 同源是指文档的来源相同,主要包括三个方面 协议 主机 载入文档的URL端口 所以同源策略就是指脚本只能读取和所属文 ...

  7. 浏览器同源策略,跨域请求jsonp

    浏览器的同源策略 浏览器安全的基石是"同源政策"(same-origin policy) 含义: 1995年,同源政策由 Netscape 公司引入浏览器.目前,所有浏览器都实行这 ...

  8. 浏览器同源策略与ajax跨域方法汇总

    原文 什么是同源策略 如果你进行过前端开发,肯定或多或少会听说过.接触过所谓的同源策略.那么什么是同源策略呢? 要了解同源策略,首先得理解“源”.在这个语境下,源(origin)其实就是指的URL.所 ...

  9. Ajax中的同源政策

    Ajax中的同源政策 Ajax请求限制 Ajax只能向自己的服务器发送请求.比如现在有一个A网站.有一个B网站,A网站中的HTML文件只能向A网站服务器中发送Ajax请求,B网站中的HTML文件只能向 ...

随机推荐

  1. [QT] - HTTP文件传输服务器#工程源码

    简介: 大学时期学习弄的一个小软件,当初做的目的是在实验室的局域网内方便同学之间文件的传输,软件的几个功能截图如正文所示,文末提供工程源码文件,感谢支持! 功能截图: [ 打开软件,选择IP及需绑定的 ...

  2. canal使用入坑,亲测 !!!!

    原来用windows本地运行,在本地模拟客户端和服务端,鼓捣了一天都没运行成功...最后放弃了,改用 windows的客户端+ubuntu的服务端(客户端程序运行在window,canal监听运行在U ...

  3. Linux系统 关机/重启/用户切换/注销,用户管理(用户创建/修改,用户组增加/删除),Linux中 / 和 ~ 的区别

    1.关机/重启命令 shutdown命令 shutdown -h now :立即关机 shutdown -h 1 :1分钟后关机 shutdown -r now :立即重启 shutdown -r 1 ...

  4. VM配置Centos(第十三步分区设置)

    1.点击开启此虚拟机之后,选择第一个 (注意:如果鼠标不显示出来,按alt+ctrl键) 2.然后选择skip跳过检测,如果选择了ok就会有很长时间的检测 3.然后选择NEXT 4.选择中文,然后点击 ...

  5. 给定一个二叉搜索树的根节点 root 和一个值 key,删除二叉搜索树中的 key 对应的节点,并保证二叉搜索树的性质不变。返回二叉搜索树(有可能被更新)的根节点的引用

    一般来说,删除节点可分为两个步骤: 首先找到需要删除的节点: 如果找到了,删除它. 说明: 要求算法时间复杂度为 O(h),h 为树的高度. 示例: root = [5,3,6,2,4,null,7] ...

  6. 实现动态WEB内容

    在 system1 上配置提供动态web内容,要求: 1.动态内容由名为 wsgi.group8.example.com 的虚拟主机提供 2.虚拟主机侦听在端口 8909 3.从 http://ser ...

  7. git 学习笔记--Feature分支

    软件开发中,总有无穷无尽的新的功能要不断添加进来. 添加一个新功能时,你肯定不希望因为一些实验性质的代码,把主分支搞乱了,所以,每添加一个新功能,最好新建一个feature分支,在上面开发,完成后,合 ...

  8. mysql 查询导出 excel 中文乱码 解决 --default-character-set=gbk

    mysql  --default-character-set=gbk -uroot -p   -D open_fusion -e  " select * from table1  " ...

  9. 入门wpf—— 3、样式

    转载于:https://www.cnblogs.com/huangxincheng/category/388852.html 这个楼主写的很详解,也比较基础,刚学wpf的朋友看看很有帮助. 说起样式, ...

  10. custom drawer

    import 'package:flutter/material.dart'; main() => runApp(MaterialApp( home: HomePage(), )); class ...