同源策略三要素
发布时间:2025-05-20 13:52:01 发布人:远客网络
一、同源策略三要素
1、同源策略三要素:协议相同、域名相同、端口相同。
2、同源策略的规定可以概括成:不同域的客户端脚本在没明确授权的情况下,不能读写对方的资源,主要有三要素:协议相同、域名相同、端口相同。
3、同源策略(Same origin policy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。
4、同源策略,它是由Netscape提出的一个著名的安全策略。当一个浏览器的两个tab页中分别打开来百度和谷歌的页面。当浏览器的百度tab页执行一个脚本的时候会检查这个脚本是属于哪个页面的,即检查是否同源,只有和百度同源的脚本才会被执行。如果非同源,那么在请求数据时,浏览器会在控制台中报一个异常,提示拒绝访问。
5、同源策略是浏览器的行为,是为了保护本地数据不被JavaScript代码获取回来的数据污染,因此拦截的是客户端发出的请求回来的数据接收,即请求发送了,服务器响应了,但是无法被浏览器接收。
二、JavaScript跨域总结与解决办法 什么是跨域
JavaScript出于安全方面的考虑,不允许跨域调用其他页面的对象。但在安全限制的同时也给注入iframe或是ajax应用上带来了不少麻烦。这里把涉及到跨域的一些问题简单地整理一下:
首先什么是跨域,简单地理解就是因为JavaScript同源策略的限制,a.com域名下的js无法操作b.com或是c.a.com域名下的对象。
第一,如果是协议和端口造成的跨域问题“前台”是无能为力的,
第二:在跨域问题上,域仅仅是通过“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的办法来解决。具体的做法是可以在和两个文件中分别加上document.domain=‘a.com’;然后通过a.html文件中创建一个iframe,去控制iframe的contentDocument,这样两个js文件之间就可以“交互”了。当然这种办法只能解决主域相同而二级域名不同的情况,如果你异想天开的把script.a.com的domian设为alibaba.com那显然是会报错地!代码如下:
var ifr= document.createElement('iframe');
ifr.src=';;
ifr.style.display='none';
document.body.appendChild(ifr);
var doc= ifr.contentDocument|| ifr.contentWindow.document;
alert(doc.getElementsByTagName("h1")[0].childNodes[0].nodeValue);
这种方式适用于{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。
虽然浏览器默认禁止了跨域访问,但并不禁止在页面中引用其他域的JS文件,并可以自由执行引入的JS文件中的function(包括操作cookie、Dom等等)。根据这一点,可以方便地通过创建script节点的方法来实现完全跨域的通信。具体的做法可以参考YUI的Get Utility
这里判断script节点加载完毕还是蛮有意思的:ie只能通过script的readystatechange属性,其它浏览器是script的load事件。以下是部分判断script加载完毕的方法。
if(!this.readyState|| this.readyState==='loaded'|| this.readyState==='complete'){
js.onload= js.onreadystatechange= null;
这个办法比较绕,但是可以解决完全跨域情况下的脚步置换问题。原理是利用location.hash来进行传值。在url: 中的‘#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文件:
var ifr= document.createElement('iframe');
ifr.style.display='none';
ifr.src=';;
document.body.appendChild(ifr);
var data= location.hash? location.hash.substring(1):'';
console.log('Now the data is'+data);
parent.location.hash='somedata';
// ie、chrome的安全机制无法修改parent.location.hash,
//所以要利用一个中间的cnblogs域下的代理iframe
var ifrproxy= document.createElement('iframe');
ifrproxy.style.display='none';
ifrproxy.src='注意该文件在"a.com"域下
document.body.appendChild(ifrproxy);
parent.parent.location.hash= self.location.hash.substring(1);
当然这样做也存在很多缺点,诸如数据直接暴露在了url中,数据容量和类型都有限等……
4、window.name实现的跨域数据传输
文章较长列在此处不便于阅读,详细请看window.name实现的跨域数据传输。
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,“*”表示不作限制
<script type="text/javascript">
var ifr= document.getElementById('ifr');
var targetOrigin='若写成';效果一样//若写成';就不会执行postMessage了
ifr.contentWindow.postMessage('I was there!', targetOrigin);
window.addEventListener('message', function(event){
//通过origin属性判断消息来源地址
if(event.origin==';){
alert(event.data);//弹出"I was there!"
alert(event.source);//对a.com、index.html中window对象的引用
//但由于同源策略,这里event.source不可以访问window对象
参考文章:《精通HTML5编程》第五章——跨文档消息机制、
这是从YUI3的IO组件中看到的办法,具体可见。
可以看在Adobe Developer Connection看到更多的跨域代理文件规范:ross-Domain Policy File Specifications、HTTP Headers Blacklist。
三、JavaScript的目的
1、从今天起我将陆续将 ppk on JavaScript的读书心得发布到这个blog上 ppk是我所景仰的一位web开发者原因无它只是因为作为一个JavaScript的开发者来说他涉及的领域包括web标准可用性无障碍等正是其他开发者所不关注或者故意忽略的并且他写了很多案例测试不同的浏览器总结出JavaScript的接口(API)兼容性成为JavaScript开发者重要参考资料几年如一日这种钻研精神是很多人所缺乏的
2、 ppk在今年月出版了他的书我从去年起就在等的书今天拿到手迫不及待地把第一章阅读完毕果然让人充满惊喜他的功力非同一般虽然只是一个初学者但我认为我已经走在正确的学习道路上我想我若能将学习心得分享能让正在学习的人看到可以一起交流一起进步尽管我不敢确保你能从我这里得到什么启发但我可以确信我这些笔记会比你拷贝粘贴代码的学习方式更正确
3、这本书有十章章名都简洁明了分别是目的背景浏览器准备核心 BOM事件 DOM CSS更改和数据获取从来没有一本书能如此简洁地明确JavaScript的方方面面因此学习不会有太大负担前言不宜过多下面就开始我的第一章学习笔记
4、开篇宗义 JavaScript的目的是为网页增加特别的一层可用性听起来很简单但这条黄金定律经常被人误解就算编写有用的JavaScript开发者可能还是没能结合适当的情景 Web标准运动发展下与当代无障碍的HTML页面的配合更为不妙的是有些开发者不是为网页增加一层可用性而是用整层取代之后果是如果浏览器不支持JavaScript网站就完了
5、 JavaScript是一门由浏览器解释的脚本语言它通过在客户端而不是服务器端处理某些交互比如表单验证创建新菜单来给网站增添可用性传统的网页交互是客户端的一举一动都必须经过服务器端的出来才能反馈回来漫长的等待会让用户崩溃而JavaScript可以在客户端代替服务器端做某些事情(最明显的表单验证)从而提高用户体验
6、随着时代的发展 JavaScript能够处理越来越多的交互问题出现了 JavaScript能做这么多事情到底要多用还是少用?这就有了富与瘦的对决是整个页面都用JavaScript来控制交互还是只增加些许的JavaScript来增强可用性?就是说尽可能地使用JavaScript还是有所节制甚至不用?
7、瘦客户端很大程度上依赖于客户端-服务器的通讯而富客户端尽可能限制额外的数据通讯
8、哪种方式更好?尽管富客户端带来一些可用性益处但瘦客户端可能是更标准的JavaScript用法 Web被认为是文档集合而不是界面集合最明显的证据是浏览器有后退前进的功能让你在文档中跳转而界面会有么?浏览器可以收藏(书签)文档而界面可以么?从无障碍来说瘦客户端也更少出错
9、这种非平衡性是很难解决的富客户端当然也可以在更高级的界面做到前进后退或者收藏也可以做到完美的无障碍这必须需要大量的额外工作但不是每个项目都有超出预算的时间或金钱此外太过专注于可用性而忽略无障碍也是一个问题
10、那么JavaScript的目的是为富客户端还是瘦客户端服务?答案是看情况得看你的网站你的受众你的JavaScript水平
11、 JavaScript分为六个方面分别是核心(Core)浏览器对象模型(BOM)事件(Events)文档对象模型(DOM) CSS变更和数据获取(XMLHttpRequest)
12、上古时代 NetScape领头之时 NetScape是事实标准
13、当代却没有这么简单 ECMA标准化JavaScript Core W C标准化DOM而BOM尚在WHAT WG的标准化中 W C也刚有了XMLHttpRequest的第一份草稿今天 BOM依然遵循NetScape的事实标准而XMLHttpRequest还是遵照Microsoft的原始规范
14、 JavaScript的目的在于为网站增加可用性而不是破坏用户的隐私和安全因此JavaScript不允许读写用户的文件(cookies除外)采取同源策略只允许来自相同域的交互不允许读取历史记录不能为上传文件的表单设置值由JavaScript控制的窗口关闭需经用户确认由JavaScript打开的窗口不能小于×的窗口不能移出屏幕之外
15、探寻历史才能让我们知道JavaScript为什么会被误解得如此深 JavaScript的创造者是Brendan Eich首次在NetScape中实现它的目的是创建一门足够简单的语言让开发者能容易地为网页增加交互只要把代码拷贝过来调整一下就可以这确实令人赞叹很多JavaScript开发者是从拷贝粘贴开始的
16、不幸的是JavaScript生错了名字也生错了语法最初它叫LiveScript但年的时候Java炙手可热 NetScape想搭顺风车于是某产品经理(我想知道她/他是谁呵呵)命令更名命令Brendan Eich让 Javascript像Java这让很多人误认为JavaScript是Java的低级版不能引起严肃程序员的关注
17、年之时 NetScape是王 Microsoft只能照抄这是一个难得的和谐期当然那时候浏览器比起现在来瘦了仅限于表单验证鼠标轮换的一些小花招而已
18、接下来就是影响深远的浏览器大战了为了争夺市场两家浏览器纷纷实现不同的东西谁都想成为事实标准最有名的就是NetScape的document layer和IE的document all(忘记它们吧!)它们让DHTML流行起来
19、年Microsoft以推出良好支持CSS和DOM的IE胜出 NetScape的让位终于有足够的时间让一场革命发生那就是CSS WaSP首先从CSS入手而很多专家也发现/发明了许多浏览器的补救办法让这场革命成为可能
20、年一些先锋们在CSS革命的影响下开始探索新的JavaScript风格更多地关注无障碍改观人们对它的坏名声那就是unobstrusive——把JavaScript从HTML结构层分离出来遗憾的是那些在浏览器大战存活下来的程序员可能还没有发现这条新道路
21、年 Ajax热潮为JavaScript社区注入新的血液但某些方面 Ajax太像DHTML了无障碍是很多Ajax应用的难言之隐这个热潮趋向于关注技术(如何Ajax)而可用性和交互(为何Ajax)却被低估最后各种肿胀的库(现在称为框架)迅速发展起来
22、 Ajax依然全速前进但这会像DHTML一样结果人们渐渐失去兴趣它们会土崩瓦解