Spring Security 中 CSRF 防御源码解析

番茄系统家园 · 2022-04-07 05:06:22

Spring Security 中 CSRF 防御源码解析

上篇文章松哥和大家聊了什么是 CSRF 攻击,以及 CSRF 攻击要如何防御。主要和大家聊了 Spring Security中处理该问题的几种办法。

今天松哥来和大家简单的看一下 Spring Security 中,CSRF 防御源码。

本文主要从两个方面来和大家讲解:

  • 返回给前端的 _csrf 参数是如何生成的。
  • 前端传来的 _csrf 参数是如何校验的。

1.随机字符串生成

我们先来看一下 Spring Security 中的 csrf 参数是如何生成的。

首先,Spring Security 中提供了一个保存 csrf 参数的规范,就是 CsrfToken:

这里三个方法都好理解,前两个是获取 _csrf 参数的 key,第三个是获取 _csrf 参数的 value。

CsrfToken 有两个实现类,如下:

Spring Security 中 CSRF 防御源码解析

默认情况下使用的是 DefaultCsrfToken,我们来稍微看下 DefaultCsrfToken:

这段实现很简单,几乎没有添加额外的方法,就是接口方法的实现。

CsrfToken 相当于就是 _csrf 参数的载体。那么参数是如何生成和保存的呢?这涉及到另外一个类:

这里三个方法:

CsrfTokenRepository 有四个实现类,在上篇文章中,我们用到了其中两个:HttpSessionCsrfTokenRepository和CookieCsrfTokenRepository,其中 HttpSessionCsrfTokenRepository 是默认的方案。

Spring Security 中 CSRF 防御源码解析

我们先来看下 HttpSessionCsrfTokenRepository 的实现:

这段源码其实也很好理解:

这是默认的方案,适用于前后端不分的开发,具体用法可以参考上篇文章。

如果想在前后端分离开发中使用,那就需要 CsrfTokenRepository 的另一个实现类CookieCsrfTokenRepository,代码如下:

和 HttpSessionCsrfTokenRepository 相比,这里 _csrf 数据保存的时候,都保存到cookie中去了,当然读取的时候,也是从 cookie 中读取,其他地方则和 HttpSessionCsrfTokenRepository 是一样的。

OK,这就是我们整个 _csrf 参数生成的过程。

总结一下,就是生成一个 CsrfToken,这个 Token,本质上就是一个 UUID 字符串,然后将这个 Token 保存到HttpSession中,或者保存到 Cookie 中,待请求到来时,从 HttpSession 或者 Cookie 中取出来做校验。

2.参数校验

那接下来就是校验了。

校验主要是通过 CsrfFilter 过滤器来进行,我们来看下核心的 doFilterInternal 方法:

这个方法我来稍微解释下:

如此之后,就完成了整个校验工作了。

3.LazyCsrfTokenRepository

前面我们说了 CsrfTokenRepository有四个实现类,除了我们介绍的两个之外,还有一个LazyCsrfTokenRepository,这里松哥也和大家做一个简单介绍。

在前面的 CsrfFilter 中大家发现,对于常见的 GET 请求实际上是不需要 CSRF 攻击校验的,但是,每当GET请求到来时,下面这段代码都会执行:

生成 CsrfToken 并保存,但实际上却没什么用,因为 GET 请求不需要 CSRF 攻击校验。

所以,Spring Security 官方又推出了 LazyCsrfTokenRepository。

LazyCsrfTokenRepository 实际上不能算是一个真正的CsrfTokenRepository,它是一个代理,可以用来增强HttpSessionCsrfTokenRepository 或者CookieCsrfTokenRepository 的功能:

这里,我说三点:

使用了 LazyCsrfTokenRepository 之后,只有在使用 csrfToken 时才会去存储它,这样就可以节省存储空间了。

LazyCsrfTokenRepository 的配置方式也很简单,在我们使用 Spring Security 时,如果对csrf不做任何配置,默认其实就是 LazyCsrfTokenRepository+HttpSessionCsrfTokenRepository 组合。

当然我们也可以自己配置,如下:

4.小结

今天主要和小伙伴聊了一下 Spring Security 中 csrf 防御的原理。

整体来说,就是两个思路:

生成 csrfToken 保存在 HttpSession 或者 Cookie 中。

请求到来时,从请求中提取出来 csrfToken,和保存的 csrfToken 做比较,进而判断出当前请求是否合法。

本文转载自微信公众号「江南一点雨」,可以通过以下二维码关注。转载本文请联系江南一点雨公众号。

Spring Security 中 CSRF 防御源码解析

免责声明: 凡标注转载/编译字样内容并非本站原创,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。如果你觉得本文好,欢迎推荐给朋友阅读;本文链接: https://m.nndssk.com/dngz/330403c5LXmh.html
猜你喜欢
最新应用
热门应用