CSRF(Cross-Site Request Forgery)即跨站请求伪造,是一种常见的 Web 安全漏洞。攻击者通过诱导用户在已登录的网站上执行恶意操作,利用用户的身份信息绕过身份验证。例如,用户在登录银行网站后,未退出登录,此时访问了恶意网站,恶意网站可能会伪装成用户向银行网站发送转账请求,由于用户处于登录状态,银行网站会认为是用户本人操作,从而导致资金损失。
在 Spring Security 中,默认情况下 CSRF 保护是开启的。下面是一个简单的 Java 配置示例:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.csrf(csrf -> csrf
// 开启 CSRF 保护
.ignoringAntMatchers("/public/**") // 忽略某些请求路径
)
.authorizeRequests(authorize -> authorize
.antMatchers("/public/**").permitAll()
.anyRequest().authenticated()
)
.formLogin();
return http.build();
}
}
在上述代码中,我们使用 csrf()
方法开启 CSRF 保护,并通过 ignoringAntMatchers()
方法忽略了 /public/**
路径的 CSRF 检查。
当 CSRF 保护开启时,表单提交需要包含 CSRF 令牌。在 JSP 中,可以使用 Spring 的标签库来自动添加 CSRF 令牌:
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<!DOCTYPE html>
<html>
<head>
<title>CSRF 表单示例</title>
</head>
<body>
<form action="/submit" method="post">
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}">
<input type="text" name="message" placeholder="输入消息">
<input type="submit" value="提交">
</form>
</body>
</html>
在上述代码中,我们通过 ${_csrf.parameterName}
和 ${_csrf.token}
获取 CSRF 令牌的参数名和值,并将其添加到表单的隐藏字段中。
如果使用 Thymeleaf 作为模板引擎,可以更方便地处理 CSRF 令牌:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>CSRF 表单示例</title>
</head>
<body>
<form action="#" th:action="@{/submit}" th:method="post">
<input type="text" name="message" placeholder="输入消息">
<input type="submit" value="提交">
</form>
</body>
</html>
Thymeleaf 会自动在表单中添加 CSRF 令牌。
在某些情况下,可能需要禁用 CSRF 保护,例如开发 RESTful API 时。可以通过以下方式禁用:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.csrf(csrf -> csrf
// 禁用 CSRF 保护
.disable()
)
.authorizeRequests(authorize -> authorize
.anyRequest().authenticated()
)
.formLogin();
return http.build();
}
}
在上述代码中,我们使用 disable()
方法禁用了 CSRF 保护。
操作 | 代码示例 | 适用场景 |
---|---|---|
配置 CSRF 保护 | http.csrf(csrf -> csrf.ignoringAntMatchers("/public/**")) |
普通 Web 应用,需要保护用户免受 CSRF 攻击 |
在 JSP 中添加 CSRF 令牌 | <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"> |
使用 JSP 作为视图层的 Web 应用 |
在 Thymeleaf 中添加 CSRF 令牌 | 无需手动添加,Thymeleaf 自动处理 | 使用 Thymeleaf 作为视图层的 Web 应用 |
禁用 CSRF 保护 | http.csrf(csrf -> csrf.disable()) |
开发 RESTful API 等不需要 CSRF 保护的场景 |
通过以上配置和禁用 CSRF 保护的方法,可以根据应用的实际需求来保障 Web 应用的安全性。