本文首发于我的Github博客
本篇文章介绍了CORS和CSRF的概念(作者前几天在和带佬们聊天的时候把两个概念搞混了,所以才想要了解),简单来说:
- CORS(Cross Origin Resource Sharing)跨域资源分享 是一种机制,通过在HTTP响应头中加入特定字段限制不同域的资源请求
- CSRF(Cross Site Request Forgery)跨站请求伪造 是一种web攻击手段,通过向服务器发送伪造请求,进行恶意行为的攻击手段
CORS(Cross Origin Resource Sharing)跨域资源分享
什么是域与跨域
在讨论跨域之前,我们需要知道域是什么
域是(scheme, host, port)三元组,也就是协议+主机+端口
只要上述三者中有任何一个不同,就说是两个不同的域
在web app中,经常会有一个站点请求另一个站点的资源的情况,比如
- 前端App运行在
localhost:3000
上 - 后端App运行在
localhost:8080
上 - 前端调用
axios
向后端发起API请求,也就是localhost:3000
到localhost:8080
的请求 - 这样的请求就是跨域请求
CORS(跨域资源分享)的目的和实现思想
因为服务器方不希望随便一个什么域都能够想自己发送请求,或者通过请求获取资源,所以想出了CORS机制进行限制
首先我们细数一下一个web app进行请求的过程:
- app发起请求
- 浏览器收到app发起的请求,将真正的网络请求发到另外的站点上
- 浏览器收到站点的响应
- 浏览器将响应交给app处理
CORS的实现思想就是在请求过程中做手脚,达到限制站点发送请求或者接受响应的目的
CORS对于普通HTTP请求的修改
所谓普通HTTP请求,就是指GET这种请求
HTTP协议认为GET应该只会从服务器获取资源,不会对服务器本身数据做出改变,所以基本上是安全的
原先请求的流程被修改为:
- app发起请求
- 浏览器收到app发起的请求,将真正的网络请求发到另外的站点上
- 浏览器收到站点的响应
- 浏览器检查响应头是否允许当前域执行GET请求
- 如不允许,就报错并丢弃数据
- 如果允许,浏览器将响应交给app处理
所以浏览器是在执行请求之后进行了检查和限制
CORS对于preflight请求的修改
preflight请求,指的是POST这种会对服务器本身数据做出改变的请求,很可能会造成严重恶意后果
原先请求的流程修改为:
- app发起请求
- 浏览器收到app发起的请求(比如POST),先发送一个正常请求(OPTIONS请求)到目标站点上
- 收到响应后,检查响应头是否允许当前站点向目标站点发起POST请求,
- 如果允许,将真正的网络请求发到另外的站点上
- 浏览器收到站点的响应
- 浏览器将数据交给app处理
- 如果不允许,直接报错
- 如果允许,将真正的网络请求发到另外的站点上
所以浏览器是在执行请求之前进行了检查和限制
CSRF(Cross Site Request Forgery)跨站请求伪造
CSRF是一种攻击手段,CORS的一个重要作用就是防范CSRF
由于我们的浏览器只是个发送请求的代发工具人,所以服务器收到请求时,并不能知道请求是如何被制造出来的
那么可以有这样的场景:
- 我要上www.aabbcc.com网站
- 结果点到了www.aabbccc.com网站
- 我输入了www.aabbcc.com的用户名和密码
- www.aabbccc.com利用我输入的用户名密码向www.aabbcc.com的服务器地址(假设为123.123.123.123:3000)发送恶意请求
这样就是www.aabbccc.com
伪造了www.aabbcc.com
的请求,并发送了,这就是CSRF(跨站请求伪造)
但是如果我们有CORS,在123.123.123.123:3000
的响应头中指出只有www.aabbcc.com
可以发送请求过来,那么www.aabbccc.com
发送的请求就会被CORS和浏览器协作清除掉,www.aabbccc.com
也就无法恶意攻击了