SpringSecurity框架下实现CSRF跨站攻击防御
程序员文章站
2022-04-14 19:39:08
一、什么是CSRF 很多朋友在学习Spring Security的时候,会将CORS(跨站资源共享)和CSRF(跨站请求伪造)弄混,以为二者是一回事。其实不是,先解释一下: CORS(跨站资源共享)是局部打破同源策略的限制,使在一定规则下HTTP请求可以突破浏览器限制,实现跨站访问。 CSRF是一种 ......
一、什么是csrf
很多朋友在学习spring security的时候,会将cors(跨站资源共享)和csrf(跨站请求伪造)弄混,以为二者是一回事。其实不是,先解释一下:
- cors(跨站资源共享)是局部打破同源策略的限制,使在一定规则下http请求可以突破浏览器限制,实现跨站访问。
- csrf是一种网络攻击方式,也可以说是一种安全漏洞,这种安全漏洞在web开发中广泛存在。
当我们使用spring security的时候,这种csrf漏洞默认的被防御掉了。但是你会发现在跨域请求的情况下,我们的post、delete、put等http请求方式失效了。所以在笔者之前的文章中,我们使用http.csrf.disable()
暂时关闭掉了csrf的防御功能,但是这样是不安全的,那么怎么样才是正确的做法呢?就是本文需要向大家介绍的内容。
二、csrf的攻击方式
通常的csrf攻击方式如下:
- 你登录了网站a,攻击者向你的网站a账户发送留言、伪造嵌入页面,带有危险操作链接。
- 当你在登录状态下点击了攻击者的连接,因此该链接对你网站a的账户进行了操作。
- 这个操作是你在网站a中主动发出的,并且也是针对网站a的http链接请求,同源策略无法限制该请求。
三、如何防御csrf攻击
- 为系统中的每一个连接请求加上一个token,这个token是随机的,服务端对该token进行验证。破坏者在留言或者伪造嵌入页面的时候,无法预先判断csrf token的值是什么,所以当服务端校验csrf token的时候也就无法通过。所以这种方法在一定程度上是靠谱的。
- 但是如果你的电脑中毒,网络信息被劫持使用token的方法仍然不安全。所以没有绝对的安全,道高一次魔高一丈。作为开发者,我们就做到我们应该做到的。
- 跳转提示:当用户不小心点击了第三方连接,合格的应用应该提示用户相关的风险!由用户自己确认是否真的要跳转或者执行第三方连接,或者就干脆不让非可信连接在留言区等地方存在。
四、spring security的csrf token攻击防护
首先,我们要先开启防护功能,在用户登陆操作之后,生成的csrf token就保存在cookies中。
public class websecurityconfig extends websecurityconfigureradapter { @override protected void configure(httpsecurity http) throws exception { http.csrf() .csrftokenrepository(cookiecsrftokenrepository.withhttponlyfalse()) .ignoringantmatchers("/authentication"); .and() ... } }
- 使用cookiecsrftokenrepository生成csrf token放入cookie,并设置cookie的httponly=false,允许js读取该cookie。
- 使用ignoringantmatchers开放一些不需要进行csrf防护的访问路径,比如:登录授权。
至此,我们生成了csrf token保存在了cookies中,浏览器向服务端发送的http请求,都要将csrf token带上,服务端校验通过才能正确的响应。这个校验的过程并不需要我们自己写代码实现,spring security会自动处理。但是我们需要关注前端代码,如何正确的携带csrf token。
五、前端请求携带csrf token的方式
在thymeleaf模板中可以使用如下方式,在发送http请求的时候携带csrf token。如果是前后端分离的应用,或者其他模板引擎,酌情从cookies中获取csrf toekn。
5.1.在header中携带csrf token
var headers = {}; headers['x-csrf-token'] = "${_csrf.token}"; $.ajax({ headers: headers, });
5.2.直接作为参数提交。
$.ajax({ data: { "_csrf": "${_csrf.token}" } });
5.3.form表单的隐藏字段
<input type="hidden" name="${_csrf.parametername}" value="${_csrf.token}">
期待您的关注
- 向您推荐博主的系列文档:《手摸手教您学习springboot系列-16章97节》
- 本文转载注明出处(必须带连接,不能只转文字):。
上一篇: vue实例化过程
下一篇: 在 C# 中使用变量