1、什么是跨域
跨域(CORS)是指不同域名之间相互访问。跨域,指的是浏览器不能执行其他网站的脚本,它是由浏览器的同源策略所造成的,是浏览器对于JavaScript所定义的安全限制策略。
以下三个条件中有一个条件不同就会产生跨域问题
- 同一协议, 如http或https
- 同一域名或ip地址, 如www.cnblogs.com、127.0.0.1
- 同一端口, 如8080
CORS攻击
CORS攻击的前提是,目标网站完成了登录,敏感信息存在本地,未登出。好的习惯是重要网站记得及时登出。
实例一
打开 www.yinghang.com 的网站,里面有个iframe指向的是 www.yinhang.com,然后就可以偷偷摸摸搜集很多东西了。
// HTML
<iframe name="yinhang" src="www.yinhang.com"></iframe>
// JS
// 由于没有同源策略的限制,钓鱼网站可以直接拿到别的网站的Dom
const iframe = window.frames['yinhang']
const node = iframe.document.getElementById('你输入账号密码的Input')
console.log(`拿到了这个${node},我还拿不到你刚刚输入的账号密码吗`)
实例二
www.yinghang.com 网站中有个访问www.yinhang.com 的脚本。可以完成转账等操作。
<img src=http://www.yinhang.com/Transfer.php?toBankId=11&money=1000>
2、如何配置跨域
前端方案
- 使用JSONP方式实现跨域调用;
- 使用NodeJS服务器做为服务代理,前端发起请求到NodeJS服务器, NodeJS服务器代理转发请求到后端服务器;
后端方案
- nginx反向代理解决跨域
- 服务端设置Response Header(响应头部)的Access-Control-Allow-Origin
- 在需要跨域访问的类和方法中设置允许跨域访问(如Spring中使用@CrossOrigin注解);
- 继承使用Spring Web的CorsFilter(适用于Spring MVC、Spring Boot)
- 实现WebMvcConfigurer接口(适用于Spring Boot)
3、实现原理
在http协议中有这两个字段,referrer和origin。
3.1、referrer
假设当前处于A网站:http://www.exampleA.com/some_page_of_a.html 页面,通过该页面中有个链接请求到了B网站的:http://www.exampleB.com/some_page_of_b.html ,当点击链接(或者其他方法),向B网站发起请求时,HTTP请求头中将包含如下字段:referrer:http://www.exampleA.com/some_page_of_a.html
在发起请求前,调用window.localtion获取window.location.href获取当前地址栏中的请求地址 将该地址附加到referrer域中。
参考了这里写链接内容发现了有两个可能的用处
- 防止盗链,盗链的解释,请参考百度百科,当一个请求到达服务器,特别是CDN服务器的时候,CDN服务器可以根据该字段来判断来源站点是否是合作伙伴,或者是可信任的,然后再决定是否将资源返回给它
- 防止恶意请求,比如说只允许外部网站访问我的静态资源,对于动态资源,不允许从外部网站访问,这样在一定程度上可以避免CSRF攻击。当然了,依赖客户端的请求是很不可靠的,因为这个可以轻轻松松伪造。
但是referrer存在很多问题,比如说我在请求外部网站的时候,携带着url的很多参数信息,而这些信息实际上是隐私的,但是外部网站都可以看到这些数据。这可能就会产生很多问题了。
3.2、origin
和referrer很相似,将当前URI的请求参数剥离,仅剩下<schema,host,port>三元组,当且仅当三元组都相等时,才说这两个域属于同一个域,标准的浏览器,会在每次请求中都带上origin,至少在跨域操作时肯定携带,origin的提出,本身就是在HTML5中跨域操作所引入的。
具体流程:
- 当一个链接或者XMLHttpRequest去请求跨域操作,浏览器事实上的确向目标服务器发起了连接请求,并且携带这origin。
- 当服务器返回时,浏览器将检查response中是否包含Access-Control-Allow-Origin字段,当缺少这个字段时,浏览器将abort,abort的意思是不显示,不产生事件,就好像没有请求过,甚至在network区域里面都看不到。
- 当存在这个header时,浏览器将检查当前请求所在域是否在这个access-control-allow-origin所允许的域内,如果是,继续下去,如果不存在,abort!100
总结:浏览器请求前会在请求头中加上origin,服务端将允许跨域的域名写到access-control-allow-origin中,浏览器收到返回后判断access-control-allow-origin。
注意:本文归作者所有,未经作者允许,不得转载