SpringSecurity(10)——Csrf防护

本文详细解释了SpringSecurity4.x版本中如何启用并管理CSRF保护,包括CSRFToken的生成、存储、验证过程,以及在HTML表单、JSON请求和无状态API中的应用实例。还介绍了如何配置CsrfTokenRepository,如CookieCsrfTokenRepository和自定义数据库存储方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Csrf Token

从 Spring Security 4.x 开始,默认启用 CSRF 保护。该默认配置将 CSRF Token 添加到名为 _csrf 的 HttpServletRequest 属性中。

SpringSecurity的Csrf机制把请求方式分为两类来处理

  1. GET、HEAD、TRACE、OPTIONS这四类请求可以直接通过
  2. 除去上面,包括POST都要被验证携带token才能通过

为了保护 MVC 应用,Spring 会在每个生成的视图中添加一个 CSRF Token。该 Token 必须在每次修改状态的 HTTP 请求(PATCH、POST、PUT 和 DELETE)中提交给服务器。这可以保护应用免受 CSRF 攻击,因为攻击者无法从自己的页面获取此 Token。

用户登录时,系统发放一个CsrfToken值,用户携带该CsrfToken值与用户名、密码等参数完成登录,系统记录该会话的CsrfToken值,之后在用户的任何请求中,都必须带上该CsrfToken值,并由系统进行校验。这种方法需要与前端配置,包括存储CsrfToken值,以及在任何请求中(表单和ajax)携带CsrfToken值,这种配置会非常麻烦

_csrf 属性包含以下信息:

  1. token:CSRF Token 值
  2. parameterName:HTML 表单参数的名称,其中必须包含 Token 值
  3. headerName:HTTP Header 的名称,其中必须包含 Token 值

HTML表单

如果视图使用 HTML 表单,可以使用 parameterName 和 token 值添加隐藏 input

<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>

JSON请求

如果视图使用 JSON,则需要使用 headerName 和 token 值添加 HTTP 请求头信息。

  1. 在 meta 标签中包含 Token 值和 Header 名称
<meta name="_csrf" content="${_csrf.token}"/>
<meta name="_csrf_header" content="${_csrf.headerName}"/>
  1. 用 JQuery 获取 meta 标签值
var token = $("meta[name='_csrf']").attr("content");
var header = $("meta[name='_csrf_header']").attr("content");
  1. 使用这些值来设置 XHR Header
$(document).ajaxSend(function(e, xhr, options) {
   
   
    xhr.setRequestHeader(header, token);
});

无状态API

如果无状态 API 使用基于 Token 的身份验证(如 JWT),就不需要 CSRF 保护。反之,如果使用 Session Cookie 进行身份验证,就需要启用 CSRF 保护。无状态 API 无法像 MVC 配置那样添加CSRF Token,因为它不会生成任何 HTML 视图。

后端配置

@Configuration
public class WebSecurityConfigurer extends WebSecurityConfigurerAdapter {
   
   
    
    @Override
    protected void configure(HttpSecurity http) throws Exception {
   
   
        http.csrf()
          .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
    }
}

在这种情况下,可以使用 CookieCsrfTokenRepository 在 Cookie 中发送 CSRF Token,此配置将为前端设置一个名为XSRF-TOKEN 的 Cookie。由于将 HTTP-only 标志设置为 false,因此前端能使用 JavaScript 获取此 Cookie。

前端配置

通过 JavaScript 从 document.cookie 列表中搜索 XSRF-TOKEN Cookie 值。

由于该列表以字符串形式存储,因此可以使用此 regex (正则)进行检索:

const csrfToken = document.cookie.replace(/(?:(?:^|.*;\s*)XSRF-TOKEN\s*\=\s*([^;]*).*$)|^.*$/, '$1');

然后,必须向每个修改 API 状态的 REST 请求发送 Token: POST、PUT、DELETE 和 PATCH。Spring 会通过 X-XSRF-TOKEN Header 来接收它。只需使用 JavaScript Fetch API 设置即可:

fetch(url, {
   
   
  method: 'POST',
  body: /* 发送给服务器的请求体 */,
  headers: {
   
    'X-XSRF-TOKEN': csrfToken },
})

JWT配置

@Configuration
public class WebSecurityConfigurer extends WebSecurityConfigurerAdapter {
   
   
    
    @Override
    protected void configure(HttpSecurity http) throws Exception {
   
   
        http.csrf().disable();
    }
}

工作原理

Spring Security 通过 CsrfFilter 实现 CSRF 防护。CsrfFilter 会直接放行 GET、HEAD、TRACE 和 OPTIONS 等请求,同时要求可能会修改数据的 PUT、POST 和 DELETE 等请求包含 CSRF Token 请求头或参数。如果 CSRF Token 不存在或值不正确,则拒绝该请求并将响应的状态设置为 403

CsrfToken

public interface CsrfToken extends 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值