背景
本系列教程,是作为团队内部的培训资料准备的。主要以实验的方式来体验SpringSecurity的各项Feature。
接着上一篇文章3-SpringSecurity:自定义Form表单中的项目:spring-security-form,继续演示开启CSRF防护的场景(当时关闭了CSRF:.csrf().disable())。
依赖不变,核心依赖为Web,SpringSecurity与Thymeleaf:
1 | xml复制代码<dependencies> |
从官网中可以知道,CSRF防护的关键在于我们发请求时附带一个随机数(CSRF token),而这个随机数不会被浏览器自动携带(eg: Cookie就会被浏览器自动带上)。
实验0:登录时的CSRF防护
显然,我们这里的登录请求是个POST方法(SpringSecurity默认忽略”GET”, “HEAD”, “TRACE”, “OPTIONS”等幂等请求的CSRF拦截)。登录时必须携带_csrf参数,与认证信息一并提交,否则报403。
- 后端安全配置(默认开启
CSRF)
1 | java复制代码@Override |
- 前端模板(新增了
_csrf参数):
1 | html复制代码<form action="login" method="post"> |
Note:
- 当然,实际中可以将新增的
_csrf参数作为一个隐藏域进行提交:<input type="text" th:name="${_csrf.parameterName}" th:value="${_csrf.token}" hidden/> - 其实,如果我们使用默认的登录页面,可以在页面元素中看到同样有个隐藏域:
实验1:POST接口CSRF防护
通过form表单是一种发送POST请求的方式,但我们其他的请求不可能都通过form表单来提交。下面通过原生的JavaScript发起Ajax的POST请求。
- 后端接口
1 | java复制代码@Controller |
- 前端模板(新增index.html)
1 | html复制代码<head> |
Note: 前面这两个实验中用到了一些参数:_csrf.parameterName,_csrf.token,_csrf_header等,这些可以从源码中获悉:
1 | java复制代码public final class HttpSessionCsrfTokenRepository implements CsrfTokenRepository { |
实验2:退出时的CSRF防护
退出url在开启CSRF之后,直接以a标签形式请求/logout(即GET方式)会报404;此时logout必须以POST方式才可以正常退出。
1 | java复制代码public final class LogoutConfigurer<H extends HttpSecurityBuilder<H>> extends |
可采用form表单或者Ajax的形式发送POST请求,携带_csrf参数,这里以form表单为例,点击POST logout按钮,可成功退出:
1 | html复制代码<form action="logout" method="post"> |
实验3:前后端分离时的CSRF防护
前面是通过在模板引擎中接收后端传回的_csrf,这里演示下前后端分离项目如何实现CSRF防护下的安全请求。
A CsrfTokenRepository that persists the CSRF token in a cookie named “XSRF-TOKEN” and reads from the header “X-XSRF-TOKEN” following the conventions of AngularJS. When using with AngularJS be sure to use withHttpOnlyFalse().
- 后端安全配置(修改
CSRF存储类型:CookieCsrfTokenRepository)
1 | java复制代码@Override |
- 前端脚本
1 | html复制代码</body> |
Note: 这里大部分同学有个问题:Cookie都被自动带到请求中了,那攻击者不就又可以拿到了吗?
由于
Cookie中的信息对于攻击者来说是不可见的,无法伪造的,虽然Cookie被浏览器自动携带了,但攻击者能做的仅仅是用一下Cookie,而Cookie里面到底放了什么内容,攻击者是不知道的,所以将CSRF-TOKEN写在Cookie中是可以防御CSRF的,相比默认的存放在Session中,CSRF-TOKEN写在Cookie中仅仅是换了一个存储位置。
什么时候需要开启CSRF?
官方文档建议,但凡涉及到浏览器用户操作,均应启用CSRF防护。
Reference
If you have any questions or any bugs are found, please feel free to contact me.
Your comments and suggestions are welcome!
本文已参与「新人创作礼」活动,一起开启掘金创作之路。
本文转载自: 掘金