背景
本系列教程,是作为团队内部的培训资料准备的。主要以实验的方式来体验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!
本文已参与「新人创作礼」活动,一起开启掘金创作之路。
本文转载自: 掘金