Spring Security 全方位教程:从入门到实战
目录
- 为什么是 Spring Security?
- 核心概念:认证与授权
- 快速开始:你的第一个 Spring Security 应用
- 深入配置:自定义认证规则
- 用户认证:自定义用户DetailsService
- 密码加密:BCryptPasswordEncoder
- 授权:基于角色的访问控制
- 实现注销功能
- 实现“记住我”功能
- 实践:构建一个完整的 RBAC 系统
- 总结与进阶
为什么是 Spring Security?
Spring Security 是一个功能强大、高度可定制的身份验证和访问控制框架,它是 Spring 生态系统的一部分,专注于为 Java 应用程序提供企业级的安全服务。

主要特点:
- 全面的安全解决方案:涵盖了认证、授权、攻击防护(如 CSRF、Session Fixation)、方法安全等。
- 高度可定制:虽然开箱即用,但你可以轻松地替换其任何组件来满足特定需求。
- 与 Spring 框架无缝集成:与 Spring Boot、Spring MVC 等完美配合,配置简单。
- 社区活跃,文档丰富:遇到问题很容易找到解决方案。
核心概念:认证与授权
在深入代码之前,必须理解两个最基本的安全概念:
a. 认证
认证 是 “你是谁?” 的过程,系统通过验证用户的凭证(如用户名/密码、令牌、生物特征等)来确认用户的身份。
- 例子:你输入用户名
admin和密码123456,系统验证这个组合是否正确,如果正确,你就被认证了。
b. 授权
授权 是 “你能做什么?” 的过程,在认证之后,系统根据用户的身份和角色,决定其可以访问哪些资源或执行哪些操作。

- 例子:认证后,系统知道
admin角色可以删除文章,而user角色只能查看文章,这就是授权。
快速开始:你的第一个 Spring Security 应用
我们将使用 Spring Initializr 快速创建一个项目。
步骤 1:创建项目
访问 start.spring.io,配置如下:
- Project: Maven Project
- Language: Java
- Spring Boot: 3.x.x (推荐最新稳定版)
- Project Metadata:
- Group:
com.example - Artifact:
security-demo - Name:
security-demo - Packaging: Jar
- Java: 17 或更高版本
- Group:
- Dependencies:
Spring Web: 用于创建 Web 应用。Spring Security: 核心安全依赖。
点击 "GENERATE" 下载项目并导入你的 IDE (如 IntelliJ IDEA 或 VS Code)。
步骤 2:创建一个简单的 Controller
在 src/main/java/com/example/securitydemo 目录下创建一个 HomeController.java。

package com.example.securitydemo;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HomeController {
@GetMapping("/hello")
public String hello() {
return "Hello, World!";
}
@GetMapping("/admin")
public String admin() {
return "Welcome, Admin!";
}
}
步骤 3:运行并测试
- 运行
SecurityDemoApplication.java主类。 - 打开浏览器,访问
http://localhost:8080/hello。 - 你会发现:浏览器没有直接显示 "Hello, World!",而是跳转到了一个 Spring Security 默认的登录页面!
发生了什么?
只要你添加了 Spring Security 依赖,你的应用就会被自动保护,所有 URL 默认都需要身份认证,Spring Security 提供了一个默认的用户名 user 和一个在启动时随机生成的密码(你可以在控制台日志中找到)。
步骤 4:使用默认用户登录
- 在登录页面,输入用户名
user和控制台日志中显示的密码。 - 登录成功后,你将被重定向到
/hello页面,看到 "Hello, World!"。
同样,访问 /admin 也能看到 "Welcome, Admin!",这是因为默认配置下,所有认证用户都可以访问所有路径。
深入配置:自定义认证规则
默认的登录页面和用户名/密码显然不适用于生产环境,我们需要自定义规则,在 Spring Boot 中,最简单的方式是继承 WebSecurityConfigurerAdapter(虽然在新版本中不推荐,但为了理解原理,我们先从这里开始)。
步骤 1:创建安全配置类
创建一个 SecurityConfig.java 类。
package com.example.securitydemo;
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.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
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.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
@Configuration
@EnableWebSecurity // 启用 Spring Security 的 Web 安全功能
public class SecurityConfig extends WebSecurityConfigurerAdapter {
// 1. 定义密码编码器(为了简单,我们先使用 NoOpPasswordEncoder,但强烈不推荐!)
@Bean
public PasswordEncoder passwordEncoder() {
return NoOpPasswordEncoder.getInstance(); // 明文密码,仅用于演示
}
// 2. 定义用户详情服务
@Override
@Bean
public UserDetailsService userDetailsService() {
UserDetails user = User.withUsername("user")
.password("password")
.roles("USER")
.build();
UserDetails admin = User.withUsername("admin")
.password("admin")
.roles("ADMIN")
.build();
return new InMemoryUserDetailsManager(user, admin);
}
// 3. 配置 HTTP 安全规则
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests() // 开启请求权限配置
.antMatchers("/hello").hasRole("USER") // /hello 需要 USER 角色
.antMatchers("/admin").hasRole("ADMIN") // /admin 需要 ADMIN 角色
.anyRequest().authenticated() // 其他所有请求都需要认证
.and()
.formLogin() // 启用表单登录
.loginPage("/login") // 自定义登录页面 (需要自己创建)
.permitAll() // 允许所有人访问登录页面
.and()
.logout() // 启用注销
.permitAll(); // 允许所有人访问注销
}
}
代码解析:
@EnableWebSecurity: 启用安全配置。passwordEncoder(): 定义了如何处理密码。NoOpPasswordEncoder是不安全的,仅用于演示! 生产环境必须使用加密编码器(如 BCrypt)。userDetailsService(): 在内存中创建了两个用户:user(角色 USER)和admin(角色 ADMIN)。configure(HttpSecurity): 这是核心,定义了访问控制规则。.antMatchers("/hello").hasRole("USER"): 指定访问/hello必须具备USER角色。.formLogin(): 启用默认的表单登录机制,并指定了自定义登录页路径。.logout(): 启用注销功能。
步骤 2:创建自定义登录页面
在 src/main/resources/templates 目录下创建 login.html (需要 Thymeleaf 依赖)。
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>Login</title>
<style>
body { font-family: Arial, sans-serif; margin: 40px; }
.container { max-width: 400px; margin: 0 auto; padding: 20px; border: 1px solid #ccc; border-radius: 5px; }
input[type="text"], input[type="password"] { width: 100%; padding: 10px 