今日干货
![8b6f844b5aa6bab0cf1c0b913322f3ef.png](https://i-blog.csdnimg.cn/blog_migrate/6966bda7dfb7a7b8627e54198d9081e1.jpeg)
公众号后台回复 ssm,免费获取松哥纯手敲的 SSM 框架学习干货。
上篇文章松哥和大家聊了什么是 CSRF 攻击,以及 CSRF 攻击要如何防御。主要和大家聊了 Spring Security 中处理该问题的几种办法。
今天松哥来和大家简单的看一下 Spring Security 中,CSRF 防御源码。
本文是本系列第 19 篇,阅读本系列前面文章有助于更好的理解本文:
- 挖一个大坑,Spring Security 开搞!
- 松哥手把手带你入门 Spring Security,别再问密码怎么解密了
- 手把手教你定制 Spring Security 中的表单登录
- Spring Security 做前后端分离,咱就别做页面跳转了!统统 JSON 交互
- Spring Security 中的授权操作原来这么简单
- Spring Security 如何将用户数据存入数据库?
- Spring Security+Spring Data Jpa 强强联手,安全管理只有更简单!
- Spring Boot + Spring Security 实现自动登录功能
- Spring Boot 自动登录,安全风险要怎么控制?
- 在微服务项目中,Spring Security 比 Shiro 强在哪?
- SpringSecurity 自定义认证逻辑的两种方式(高级玩法)
- Spring Security 中如何快速查看登录用户 IP 地址等信息?
- Spring Security 自动踢掉前一个登录用户,一个配置搞定!
- Spring Boot + Vue 前后端分离项目,如何踢掉已登录用户?
- Spring Security 自带防火墙!你都不知道自己的系统有多安全!
- 什么是会话固定攻击?Spring Boot 中要如何防御会话固定攻击?
- 集群化部署,Spring Security 要如何处理 session 共享?
- 松哥手把手教你在 SpringBoot 中防御 CSRF 攻击!so easy!
本文主要从两个方面来和大家讲解:
- 返回给前端的
_csrf
参数是如何生成的。 - 前端传来的
_csrf
参数是如何校验的。
1.随机字符串生成
我们先来看一下 Spring Security 中的 csrf 参数是如何生成的。
首先,Spring Security 中提供了一个保存 csrf 参数的规范,就是 CsrfToken:
public interface CsrfToken extends Serializable {
String getHeaderName();
String getParameterName();
String getToken();
}
这里三个方法都好理解,前两个是获取 _csrf
参数的 key,第三个是获取 _csrf
参数的 value。
CsrfToken 有两个实现类,如下:
![28f910d1eb844b640895bc621880bfd5.png](https://i-blog.csdnimg.cn/blog_migrate/37df5f522eb953b2fd9865923dd0333e.png)
默认情况下使用的是 DefaultCsrfToken,我们来稍微看下 DefaultCsrfToken:
public final class DefaultCsrfToken implements CsrfToken {
private final String token;
private final String parameterName;
private final String headerName;
public DefaultCsrfToken(String headerName, String parameterName, String token) {
this.headerName = headerName;
this.parameterName = parameterName;
this.token = token;
}
public String getHeaderName() {
return this.headerName;
}
public String getParameterName() {
return this.parameterName;
}
public String getToken() {
return this.token;
}
}
这段实现很简单,几乎没有添加额外的方法,就是接口方法的实现。
CsrfToken 相当于就是 _csrf
参数的载体。那么参数是如何生成和保存的呢?这涉及到另外一个类:
public interface CsrfTokenRepository {
CsrfToken generateToken(HttpServletRequest request);
void saveToken(CsrfToken token, HttpServletRequest request,
HttpServlet