首先要从头来讲。浏览器本身存在同源策略。协议,域名,端口相同,视为同一个域,一个域内的脚本仅仅具有本域内的权限,可以理解为本域脚本只能读写本域内的资源,而无法访问其它域的资源。这种安全限制称为同源策略。同源策略保证了资源的隔离。一个网站的脚本只能访问自己的资源,就像操作系统里进程不能访问另一个进程的资源一样,如果没有同源策略,你在网站浏览,跳转其他网页,然后这个网页就可以跨域读取你网站中的信息,这样整个Web世界就无隐私可言了。这就是同源策略的重要性,它限制了这些行为。当然,在同一个域内,客户端脚本可以任意读写同源内的资源,前提是这个资源本身是可读可写的。通俗的讲,浏览器有一个很重要的安全机制,即为同源策略:不用域的客户端脚本在无明确授权的情况下不能读取对方资源,跨域也就是不同源回答了浏览器的同源策略,再回答一下跨域。只要协议,域名,端口有一个不同,就是跨域,ajax请求一个目标地址为非本域(协议,域名,端口任意一个不同)的web资源,就是跨域。
1. 什么是同源?
2. 为什么要有同源策略?
同源:相同协议,相同域名,相同端口称为同源。
同源策略:在web应用的安全模型中是一个重要概念。在这个策略下,web浏览器允许第一个页面的脚本访问第二个页面里的数据,但是也只有在两个页面有相同的源时。源是由URI,主机名,端口号组合而成的。这个策略可以阻止一个页面上的恶意脚本通过页面的DOM对象获得访问另一个页面上敏感信息的权限。
源决定规则:
源就是{协议,主机,端口}定义的。只有这些值完全一样才认为两个资源是同源的。
为了举例,下面的表格给出了与URL"http://yinhang.com/zhanghu/zhanghu.html"的对比。
URI | 结果 | 原因 |
http://yinhang.com/zhanghu2/zhanghu.html | 成功 | 只有路径不同 |
http://yinhang.com/zhanghu/ZH/zhanghu.html | 成功 | 只有路径不同 |
https://yinhang.com/zhanghu/zhanghu.html | 失败 | 不同协议 ( https和http ) |
http://yinhang.com:81/zhanghu/zhanghu.html | 失败 | 不同端口 ( http:// 80是默认的) |
http://yinghang.com/zhanghu/zhanghu.html | 失败 | 不同域名 ( yinhang和yinghang) |
没有同源策略限制的Dom查询
1.有一天你刚睡醒,收到一封邮件,说是你的银行账号有风险,赶紧点www.yinghang.com改密码。你吓尿了,赶紧点进去,还是熟悉的银行登录界面,你果断输入你的账号密码,登录进去看看钱有没有少了。
2.睡眼朦胧的你没看清楚,平时访问的银行网站是www.yinhang.com,而现在访问的是www.yinghang.com,这个钓鱼网站做了什么呢?
// HTML <iframe name="yinhang" src="www.yinhang.com"></iframe>
// JS // 由于没有同源策略的限制,钓鱼网站可以直接拿到别的网站的Dom
const iframe = window.frames['yinghang'] const node = iframe.document.getElementById('你输入账号密码的Input')
console.log(`拿到了这个${node},我还拿不到你刚刚输入的账号密码吗?`)
如果没有 DOM 同源策略,也就是说不同域的 iframe 之间可以相互访问,那么黑客可以这样进行攻击:
做一个假网站,里面用 iframe 嵌套一个银行网站 “www.yinghang.com”。
把 iframe 宽高啥的调整到页面全部,这样用户进来除了域名,别的部分和银行的网站没 有任何差别。
这时如果用户输入账号密码,我们的主网站可以跨域访问到 www.yinghang.com的 dom 节点,就可以拿到用户的账户密码了。
由此我们知道,同源策略确实能规避一些危险,不是说有了同源策略就安全,只是说同源策略是一种浏览器最基本的安全机制,毕竟能提高一点攻击的成本。其实没有刺不穿的盾,只是攻击的成本和攻击成功后获得的利益成不成正比。
AJAX通过CORS跨域:
CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而解决了AJAX不能跨域请求的问题。整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。因此,实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信。CORS允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。