在现代应用开发中,安全性是不可忽视的核心问题。无论是小型应用,还是大型分布式系统,应用都需要防范来自网络的潜在攻击。Spring Boot 3 与 Spring Security 提供了一系列功能来帮助开发者构建安全、健壮的应用,尤其是在防范常见漏洞攻击方面。本文将讨论如何在 Spring Boot 3 中利用 Spring Security 来防范几类常见的漏洞攻击。
1. 防范CSRF(跨站请求伪造)
CSRF(跨站请求伪造)攻击的原理是利用用户已登录的身份,在不知情的情况下,执行恶意的操作。攻击者通常会诱导用户点击恶意链接或访问恶意网站,该请求会在用户已登录的应用中以用户的身份执行。例如,用户登录了银行账户,攻击者发送一个请求,执行转账操作,而用户并未察觉。
攻击的关键是:用户的身份验证凭据(如Cookie、Session等)会自动随请求发送,从而使恶意请求在服务器端被认为是合法的。
在默认情况下,Spring Security 会启用 CSRF 保护,特别是对于会话管理的应用。
1.1 演示效果
如果提交表单时未传 _csrf
,则会提示 403
禁止访问。
当前表单里携带了 _csrf
token 时,则请求通过。
使用 thymeleaf
模板时,会自动携带上 _csrf
token。
1.2 关闭 CSRF 防护
有些请求不涉及到状态形式运行时,如REST API,则需要关闭 CSRF 防护配置。
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.context.annotation.Bean;
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.csrf(csrf -> csrf.disable()) // 若某些请求无需 CSRF 保护可以禁用
.authorizeRequests(auth -> auth
.requestMatchers("/").permitAll()
.anyRequest().authenticated())
.formLogin();
return http.build();
}
- 启用或禁用 CSRF:当应用以无状态(stateless)形式运行时,如 REST API,CSRF 保护可以适当禁用。
- 默认防护:对于常见的 Web 应用,Spring Security 默认会自动为表单提交添加 CSRF 保护。
2. 防范XSS(跨站脚本攻击)
在 Spring Security 中,防范 XSS(跨站脚本攻击) 是非常重要的。XSS 攻击允许攻击者通过注入恶意的客户端脚本(如JavaScript)来操纵用户浏览器,从而窃取用户信息或执行其他恶意行为。Spring Security 默认提供了一些 XSS 防护机制,但我们仍需确保在前端输入和后端输出时严格过滤和转义数据。
下面是一个简单的 Spring Boot 3 和 Spring Security 演示,展示如何在应用中防范 XSS 攻击。
2.1 配置 Spring Security
配置一个简单的 Security 配置类,允许所有用户访问我们的演示页面。
package com.coderjia.boot313security.config;
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.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;
/**
* @author CoderJia
* @create 2024/10/13 下午 01:57
* @Description
**/
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests((authz) -> authz
.anyRequest().permitAll() // 允许所有请求
)
.csrf(csrf->csrf.disable()); // 这里禁用 CSRF 仅用于演示,实际开发中请根据需要启用 CSRF 防护
return http.build();
}
}
2.2 定义控制器
package com.coderjia.boot313security.controller;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.annotation.Secured;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
/**
* @author CoderJia
* @create 2024/10/13 下午 02:10
* @Description
**/
@Slf4j
@Controller
public class LoginController {
@GetMapping("/home")
public String home() {
return "xss_demo";
}
@PostMapping("/submit")
public String submit(@RequestParam String input, Model model) {
model.addAttribute("input", input);
return "xss_result";
}
}
2.3 创建 Thymeleaf 模板
xss_demo.html
(用户输入页面)
我们使用 Thymeleaf 模板展示用户输入的内容,这也是 XSS 攻击常发生的地方。如果没有适当的转义,恶意代码将被执行。
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>XSS Demo</title>
</head>
<body>
<h1>输入内容</h1>
<form action="/submit" method="post">
<input type="text" name="input" />
<button type="submit">提交</button>
</form>
</body>
</html>
xss_result.html
(展示用户输入结果)
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>结果</title>
</head>
<body>
<h1>结果</h1>
<p>您输入的内容:</p>
<!-- 使用 Thymeleaf 来自动转义用户输入的内容,防止 XSS 攻击,所有使用th:utext -->
<p th:utext="${input}"></p>
</body>
</html>
2.4 XSS 攻击演示
在没有安全防护的情况下,如果用户输入了类似以下内容:
<script>alert('XSS 攻击!')</script>
输入框输入脚本:
显示攻击:
如果我们没有使用 th:text
来转义输出,恶意脚本将被执行并弹出警告框。然而,使用 th:text
后,Thymeleaf 会自动转义 <script>
标签,防止它被执行。
2.5 启用内容安全策略(CSP)
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests((authz) -> authz
.anyRequest().permitAll() // 允许所有请求
)
.headers(headers -> headers.contentSecurityPolicy(contentSecurityPolicyConfig -> contentSecurityPolicyConfig.policyDirectives("script-src 'self'")))
.csrf(csrf->csrf.disable()); // 这里禁用 CSRF 仅用于演示,实际开发中请根据需要启用 CSRF 防护
return http.build();
}
这种配置通过**内容安全策略(CSP)**来防止外部来源的脚本加载,从而有效减少 XSS 攻击的风险。
- 输出编码:在服务端,应确保在返回 HTML 内容时,对用户输入的数据进行适当的转义处理,以防止恶意脚本注入。
3. 防范SQL注入
SQL 注入是最常见的攻击之一,通过在输入字段中插入恶意的 SQL 语句来篡改数据库。Spring Security 通过数据访问层的安全来防止 SQL 注入。
使用参数化查询:
@Query("SELECT u FROM User u WHERE u.username = :username")
User findByUsername(@Param("username") String username);
Spring Data JPA 提供了安全的参数化查询方式,避免了 SQL 注入的风险。
此外,Hibernate 作为 Spring Boot 默认的 ORM 框架,天生对 SQL 注入有很强的防护能力,确保开发者不会在使用 JPQL(Java Persistence Query Language)时受到攻击。
4. 防范暴力破解
暴力破解 是攻击者不断尝试不同的用户名和密码组合,直到找到正确的凭据。为防范暴力破解攻击,可以使用账户锁定策略和限制登录次数。
配置登录失败次数限制:
http
.formLogin(form->form.failureHandler((request, response, exception) -> {
// 如果登录失败次数过多,则锁定账户
String username = request.getParameter("username");
// 调用业务逻辑锁定账户
}));
通过设置登录失败后的延时或账户锁定策略,可以显著减少暴力破解的威胁。
5. 安全头部配置
HTTP 头部是重要的安全防护部分。Spring Security 提供了很多内建的 HTTP 头部配置来增强安全性:
http
.headers(headers -> headers
.xssProtection(Customizer.withDefaults()) // 防范XSS
.frameOptions(HeadersConfigurer.FrameOptionsConfig::sameOrigin) // 防范点击劫持
.contentTypeOptions(Customizer.withDefaults()) // 禁止内容嗅探
.httpStrictTransportSecurity(Customizer.withDefaults())); // 强制 HTTPS 连接
return http.build();
这些安全头部能够有效地防范一系列的攻击,包括Clickjacking、内容嗅探、以及通过不安全的 HTTP 协议传输敏感数据。
6. 防范Clickjacking攻击
Clickjacking 是通过将网页嵌入到恶意页面的 iframe 中,使得用户误点击,执行意图不明的操作。可以通过设置 X-Frame-Options 来防范这类攻击。
http
.headers(headers -> headers
.frameOptions(HeadersConfigurer.FrameOptionsConfig::sameOrigin)); // 防范点击劫持
这种配置将只允许页面嵌入自身的 iframe,而拒绝外部页面嵌入。
7. 总结
Spring Security 在 Spring Boot 3 中提供了丰富的防护机制,帮助开发者应对多种常见的网络攻击。从 CSRF 到 SQL 注入,XSS 攻击再到 Clickjacking,每个环节都能通过适当的配置和策略,保障应用的安全性。通过正确的防护措施,开发者不仅能避免潜在的安全漏洞,还能提高用户对应用的信任和满意度。