目录
一、CSRF是什么
CSRF(Cross-Site Request Forgery,跨站请求伪造)是一种常见的网络攻击方式,攻击者通过伪装用户的请求,利用用户在其他网站上已经登录的身份权限来执行恶意操作。为了防止 CSRF 攻击,Spring Security 提供了内置的 CSRF 保护功能。
二、Spring Security中的CSRF保护
在Spring框架中,如果引入了Spring Security依赖,除了会默认开启身份验证,同时还会开启CSRF保护功能。
启用此功能可确保,在会更改状态的HTTP请求上,如果没有带上有效的X-CSRFToken,则会出现 403 错误。
HTTP状态码403表示禁止访问,即服务器理解请求客户端的请求,但是拒绝执行这个请求。这通常是由于客户端没有足够的权限访问该资源所导致的。
可以认为安全的方法都是只读的方法(GET, HEAD, OPTIONS),这些类型的请求不会改变资源状态,被认为是幂等的,即调用相同的URL多次得到的结果不变。
DELETE方法的语义表示删除服务器上的一个资源,第一次删除成功后该资源就不存在了,资源状态改变了,所以DELETE方法不具备安全特性。然而HTTP协议规定DELETE方法是幂等的,每次删除该资源都要返回状态码200 OK,服务器端要实现幂等的DELETE方法,必须记录所有已删除资源的元数据(Metadata),否则,第二次删除后返回的响应码就会类似404 Not Found了。
PUT和POST方法语义中都有修改资源状态的意思,因此都不是安全的。但是PUT方法是幂等的,POST方法不是幂等的,这么设计的理由是:
HTTP协议规定,POST方法修改资源状态时,URL指示的是该资源的父级资源,待修改资源的ID信息在请求体中携带。而PUT方法修改资源状态时,URL直接指示待修改资源。因此,同样是创建资源,重复提交POST请求可能产生两个不同的资源,而重复提交PUT请求只会对其URL中指定的资源起作用,也就是只会创建一个资源。
因此,当Spring Security使用默认配置,或手动开启CSRF保护功能时,我们会发现,GET请求是正常的,但是POST请求会报403错误。
三、处理方法
处理方法一:跳过安全检查(不推荐,因为这个一般是用于静态资源等)
@Bean
//(Spring Security6.2.4写法)
public WebSecurityCustomizer webSecurityCustomizer() {
// 匹配的路径,直接跳过安全检查
return (web) -> web.ignoring().requestMatchers("/static/**");
}
处理方法二:关闭CSRF保护功能
@Bean
//(Spring Security6.2.4写法)
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.authorizeHttpRequests(
(authz) -> authz
.anyRequest().authenticated())
.httpBasic(withDefaults())
.formLogin(withDefaults())
.csrf((csrf)->csrf.disable());
//只对匹配路径关闭CSRF
//.csrf((csrf)->csrf.ignoringRequestMatchers("/路径"));
return http.build();
}
处理方法三:正常在请求时带上X-CSRFToken