
✨道路是曲折的,前途是光明的!
📝 专注C/C++、Linux编程与人工智能领域,分享学习笔记!
🌟 感谢各位小伙伴的长期陪伴与支持,欢迎文末添加好友一起交流!

- 目录
-
- 前言
- 一、Spring Security 是什么?
-
- 1.1 核心功能
- 二、技术组成分布
- 三、认证流程解析
-
- 3.1 请求处理流程
- 3.2 过滤器链结构
- 四、快速开始
-
- 4.1 添加依赖
- 4.2 基础配置
- 五、认证机制详解
-
- 5.1 内存认证(开发测试)
- 5.2 数据库认证(生产推荐)
- 六、授权控制方式
-
- 6.1 注解方式
- 6.2 配置方式
- 七、JWT 无状态认证
-
- 7.1 JWT 认证流程
- 7.2 JWT 实现
- 八、常见场景解决方案
-
- 8.1 场景一:记住我功能
- 8.2 场景二:退出登录
- 8.3 场景三:CSRF 防护
- 8.4 场景四:自定义登录页
- 九、学习路线
-
- 9.1 学习时间建议
- 十、最佳实践
-
- 10.1 密码加密
- 10.2 权限设计原则
- 10.3 异常处理
- 10.4 安全配置
- 十一、总结
-
- 11.1核心要点回顾
- 十二、推荐资源
目录
前言
你是否还在为权限管理发愁?手写拦截器、过滤器、权限判断?Spring Security 来拯救你了!
作为 Java 生态中最强大的安全框架,Spring Security 为企业级应用提供了完整的安全解决方案。本文带你从零掌握 Spring Security。 
一、Spring Security 是什么?
Spring Security 是一个功能强大且高度可定制的认证和访问控制框架,专注于为 Java 应用程序提供安全服务。
1.1 核心功能
| 认证 (Authentication) | 验证"你是谁" |
| 授权 (Authorization) | 验证"你能做什么" |
| 防护常见攻击 | CSRF、XSS、会话固定等 |
二、技术组成分布
#mermaid-svg-LQvXvlwP0oWbAN6v{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-LQvXvlwP0oWbAN6v .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-LQvXvlwP0oWbAN6v .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-LQvXvlwP0oWbAN6v .error-icon{fill:#552222;}#mermaid-svg-LQvXvlwP0oWbAN6v .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-LQvXvlwP0oWbAN6v .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-LQvXvlwP0oWbAN6v .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-LQvXvlwP0oWbAN6v .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-LQvXvlwP0oWbAN6v .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-LQvXvlwP0oWbAN6v .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-LQvXvlwP0oWbAN6v .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-LQvXvlwP0oWbAN6v .marker{fill:#333333;stroke:#333333;}#mermaid-svg-LQvXvlwP0oWbAN6v .marker.cross{stroke:#333333;}#mermaid-svg-LQvXvlwP0oWbAN6v svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-LQvXvlwP0oWbAN6v p{margin:0;}#mermaid-svg-LQvXvlwP0oWbAN6v .pieCircle{stroke:#000000;stroke-width:2px;opacity:0.7;}#mermaid-svg-LQvXvlwP0oWbAN6v .pieOuterCircle{stroke:#000000;stroke-width:1px;fill:none;}#mermaid-svg-LQvXvlwP0oWbAN6v .pieTitleText{text-anchor:middle;font-size:25px;fill:#000000;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}#mermaid-svg-LQvXvlwP0oWbAN6v .slice{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;fill:#000000;font-size:17px;}#mermaid-svg-LQvXvlwP0oWbAN6v .legend text{fill:#000000;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:17px;}#mermaid-svg-LQvXvlwP0oWbAN6v :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
30%
25%
20%
15%
10%
Spring Security 学习重点分布
认证机制 [30]
授权控制 [25]
过滤器链 [20]
JWT集成 [15]
OAuth2 [10]
三、认证流程解析
3.1 请求处理流程
#mermaid-svg-O4FZnxZvbM5x5neh{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-O4FZnxZvbM5x5neh .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-O4FZnxZvbM5x5neh .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-O4FZnxZvbM5x5neh .error-icon{fill:#552222;}#mermaid-svg-O4FZnxZvbM5x5neh .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-O4FZnxZvbM5x5neh .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-O4FZnxZvbM5x5neh .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-O4FZnxZvbM5x5neh .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-O4FZnxZvbM5x5neh .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-O4FZnxZvbM5x5neh .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-O4FZnxZvbM5x5neh .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-O4FZnxZvbM5x5neh .marker{fill:#333333;stroke:#333333;}#mermaid-svg-O4FZnxZvbM5x5neh .marker.cross{stroke:#333333;}#mermaid-svg-O4FZnxZvbM5x5neh svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-O4FZnxZvbM5x5neh p{margin:0;}#mermaid-svg-O4FZnxZvbM5x5neh .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-O4FZnxZvbM5x5neh .cluster-label text{fill:#333;}#mermaid-svg-O4FZnxZvbM5x5neh .cluster-label span{color:#333;}#mermaid-svg-O4FZnxZvbM5x5neh .cluster-label span p{background-color:transparent;}#mermaid-svg-O4FZnxZvbM5x5neh .label text,#mermaid-svg-O4FZnxZvbM5x5neh span{fill:#333;color:#333;}#mermaid-svg-O4FZnxZvbM5x5neh .node rect,#mermaid-svg-O4FZnxZvbM5x5neh .node circle,#mermaid-svg-O4FZnxZvbM5x5neh .node ellipse,#mermaid-svg-O4FZnxZvbM5x5neh .node polygon,#mermaid-svg-O4FZnxZvbM5x5neh .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-O4FZnxZvbM5x5neh .rough-node .label text,#mermaid-svg-O4FZnxZvbM5x5neh .node .label text,#mermaid-svg-O4FZnxZvbM5x5neh .image-shape .label,#mermaid-svg-O4FZnxZvbM5x5neh .icon-shape .label{text-anchor:middle;}#mermaid-svg-O4FZnxZvbM5x5neh .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-O4FZnxZvbM5x5neh .rough-node .label,#mermaid-svg-O4FZnxZvbM5x5neh .node .label,#mermaid-svg-O4FZnxZvbM5x5neh .image-shape .label,#mermaid-svg-O4FZnxZvbM5x5neh .icon-shape .label{text-align:center;}#mermaid-svg-O4FZnxZvbM5x5neh .node.clickable{cursor:pointer;}#mermaid-svg-O4FZnxZvbM5x5neh .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-O4FZnxZvbM5x5neh .arrowheadPath{fill:#333333;}#mermaid-svg-O4FZnxZvbM5x5neh .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-O4FZnxZvbM5x5neh .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-O4FZnxZvbM5x5neh .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-O4FZnxZvbM5x5neh .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-O4FZnxZvbM5x5neh .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-O4FZnxZvbM5x5neh .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-O4FZnxZvbM5x5neh .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-O4FZnxZvbM5x5neh .cluster text{fill:#333;}#mermaid-svg-O4FZnxZvbM5x5neh .cluster span{color:#333;}#mermaid-svg-O4FZnxZvbM5x5neh div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-O4FZnxZvbM5x5neh .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-O4FZnxZvbM5x5neh rect.text{fill:none;stroke-width:0;}#mermaid-svg-O4FZnxZvbM5x5neh .icon-shape,#mermaid-svg-O4FZnxZvbM5x5neh .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-O4FZnxZvbM5x5neh .icon-shape p,#mermaid-svg-O4FZnxZvbM5x5neh .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-O4FZnxZvbM5x5neh .icon-shape rect,#mermaid-svg-O4FZnxZvbM5x5neh .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-O4FZnxZvbM5x5neh .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-O4FZnxZvbM5x5neh .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-O4FZnxZvbM5x5neh :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
否
是
否
是
是
否
用户请求
Security Filter Chain
已认证?
认证过滤器
登录验证
成功?
创建SecurityContext
返回401
有权限?
访问资源
返回403
3.2 过滤器链结构
#mermaid-svg-BLyXhcFtbs9G2wxx{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-BLyXhcFtbs9G2wxx .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-BLyXhcFtbs9G2wxx .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-BLyXhcFtbs9G2wxx .error-icon{fill:#552222;}#mermaid-svg-BLyXhcFtbs9G2wxx .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-BLyXhcFtbs9G2wxx .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-BLyXhcFtbs9G2wxx .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-BLyXhcFtbs9G2wxx .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-BLyXhcFtbs9G2wxx .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-BLyXhcFtbs9G2wxx .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-BLyXhcFtbs9G2wxx .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-BLyXhcFtbs9G2wxx .marker{fill:#333333;stroke:#333333;}#mermaid-svg-BLyXhcFtbs9G2wxx .marker.cross{stroke:#333333;}#mermaid-svg-BLyXhcFtbs9G2wxx svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-BLyXhcFtbs9G2wxx p{margin:0;}#mermaid-svg-BLyXhcFtbs9G2wxx .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-BLyXhcFtbs9G2wxx .cluster-label text{fill:#333;}#mermaid-svg-BLyXhcFtbs9G2wxx .cluster-label span{color:#333;}#mermaid-svg-BLyXhcFtbs9G2wxx .cluster-label span p{background-color:transparent;}#mermaid-svg-BLyXhcFtbs9G2wxx .label text,#mermaid-svg-BLyXhcFtbs9G2wxx span{fill:#333;color:#333;}#mermaid-svg-BLyXhcFtbs9G2wxx .node rect,#mermaid-svg-BLyXhcFtbs9G2wxx .node circle,#mermaid-svg-BLyXhcFtbs9G2wxx .node ellipse,#mermaid-svg-BLyXhcFtbs9G2wxx .node polygon,#mermaid-svg-BLyXhcFtbs9G2wxx .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-BLyXhcFtbs9G2wxx .rough-node .label text,#mermaid-svg-BLyXhcFtbs9G2wxx .node .label text,#mermaid-svg-BLyXhcFtbs9G2wxx .image-shape .label,#mermaid-svg-BLyXhcFtbs9G2wxx .icon-shape .label{text-anchor:middle;}#mermaid-svg-BLyXhcFtbs9G2wxx .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-BLyXhcFtbs9G2wxx .rough-node .label,#mermaid-svg-BLyXhcFtbs9G2wxx .node .label,#mermaid-svg-BLyXhcFtbs9G2wxx .image-shape .label,#mermaid-svg-BLyXhcFtbs9G2wxx .icon-shape .label{text-align:center;}#mermaid-svg-BLyXhcFtbs9G2wxx .node.clickable{cursor:pointer;}#mermaid-svg-BLyXhcFtbs9G2wxx .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-BLyXhcFtbs9G2wxx .arrowheadPath{fill:#333333;}#mermaid-svg-BLyXhcFtbs9G2wxx .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-BLyXhcFtbs9G2wxx .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-BLyXhcFtbs9G2wxx .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-BLyXhcFtbs9G2wxx .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-BLyXhcFtbs9G2wxx .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-BLyXhcFtbs9G2wxx .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-BLyXhcFtbs9G2wxx .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-BLyXhcFtbs9G2wxx .cluster text{fill:#333;}#mermaid-svg-BLyXhcFtbs9G2wxx .cluster span{color:#333;}#mermaid-svg-BLyXhcFtbs9G2wxx div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-BLyXhcFtbs9G2wxx .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-BLyXhcFtbs9G2wxx rect.text{fill:none;stroke-width:0;}#mermaid-svg-BLyXhcFtbs9G2wxx .icon-shape,#mermaid-svg-BLyXhcFtbs9G2wxx .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-BLyXhcFtbs9G2wxx .icon-shape p,#mermaid-svg-BLyXhcFtbs9G2wxx .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-BLyXhcFtbs9G2wxx .icon-shape rect,#mermaid-svg-BLyXhcFtbs9G2wxx .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-BLyXhcFtbs9G2wxx .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-BLyXhcFtbs9G2wxx .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-BLyXhcFtbs9G2wxx :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
请求
ChannelProcessingFilter
SecurityContextFilter
LogoutFilter
UsernamePasswordAuthenticationFilter
ExceptionTranslationFilter
FilterSecurityInterceptor
Controller
四、快速开始
4.1 添加依赖
<!– pom.xml –>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
4.2 基础配置
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(auth -> auth
.requestMatchers("/public/**").permitAll()
.anyRequest().authenticated()
)
.formLogin(withDefaults())
.httpBasic(withDefaults());
return http.build();
}
}
五、认证机制详解
5.1 内存认证(开发测试)
@Bean
public UserDetailsService userDetailsService() {
UserDetails user = User.builder()
.username("admin")
.password(passwordEncoder().encode("123456"))
.roles("ADMIN")
.build();
UserDetails guest = User.builder()
.username("guest")
.password(passwordEncoder().encode("123456"))
.roles("GUEST")
.build();
return new InMemoryUserDetailsManager(user, guest);
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
5.2 数据库认证(生产推荐)
@Service
public class CustomUserDetailsService implements UserDetailsService {
@Autowired
private UserRepository userRepository;
@Override
public UserDetails loadUserByUsername(String username) {
User user = userRepository.findByUsername(username)
.orElseThrow(() -> new UsernameNotFoundException("用户不存在"));
return User.withUsername(user.getUsername())
.password(user.getPassword())
.roles(user.getRole())
.build();
}
}
六、授权控制方式
6.1 注解方式
// 启用注解
@EnableGlobalMethodSecurity(prePostEnabled = true)
// 使用示例
@Service
public class UserService {
@PreAuthorize("hasRole('ADMIN')")
public void deleteUser(Long id) {
// 只有ADMIN角色可以删除
}
@PreAuthorize("#userId == authentication.principal.id")
public User getUserInfo(Long userId) {
// 只能查询自己的信息
}
@PostFilter("filterObject.owner == authentication.name")
public List<Document> getAllDocuments() {
// 过滤返回结果
}
}
6.2 配置方式
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/admin/**").hasRole("ADMIN")
.requestMatchers("/api/user/**").hasAnyRole("ADMIN", "USER")
.requestMatchers(HttpMethod.POST, "/api/posts").hasAuthority("post:write")
.requestMatchers("/public/**").permitAll()
.anyRequest().authenticated()
);
return http.build();
}
七、JWT 无状态认证
7.1 JWT 认证流程
资源
服务器
用户
资源
服务器
用户
#mermaid-svg-bdTHXWwInETfZOrb{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-bdTHXWwInETfZOrb .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-bdTHXWwInETfZOrb .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-bdTHXWwInETfZOrb .error-icon{fill:#552222;}#mermaid-svg-bdTHXWwInETfZOrb .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-bdTHXWwInETfZOrb .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-bdTHXWwInETfZOrb .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-bdTHXWwInETfZOrb .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-bdTHXWwInETfZOrb .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-bdTHXWwInETfZOrb .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-bdTHXWwInETfZOrb .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-bdTHXWwInETfZOrb .marker{fill:#333333;stroke:#333333;}#mermaid-svg-bdTHXWwInETfZOrb .marker.cross{stroke:#333333;}#mermaid-svg-bdTHXWwInETfZOrb svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-bdTHXWwInETfZOrb p{margin:0;}#mermaid-svg-bdTHXWwInETfZOrb .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-bdTHXWwInETfZOrb text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-bdTHXWwInETfZOrb .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-bdTHXWwInETfZOrb .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-bdTHXWwInETfZOrb .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-bdTHXWwInETfZOrb .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-bdTHXWwInETfZOrb #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-bdTHXWwInETfZOrb .sequenceNumber{fill:white;}#mermaid-svg-bdTHXWwInETfZOrb #sequencenumber{fill:#333;}#mermaid-svg-bdTHXWwInETfZOrb #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-bdTHXWwInETfZOrb .messageText{fill:#333;stroke:none;}#mermaid-svg-bdTHXWwInETfZOrb .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-bdTHXWwInETfZOrb .labelText,#mermaid-svg-bdTHXWwInETfZOrb .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-bdTHXWwInETfZOrb .loopText,#mermaid-svg-bdTHXWwInETfZOrb .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-bdTHXWwInETfZOrb .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-bdTHXWwInETfZOrb .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-bdTHXWwInETfZOrb .noteText,#mermaid-svg-bdTHXWwInETfZOrb .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-bdTHXWwInETfZOrb .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-bdTHXWwInETfZOrb .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-bdTHXWwInETfZOrb .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-bdTHXWwInETfZOrb .actorPopupMenu{position:absolute;}#mermaid-svg-bdTHXWwInETfZOrb .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-bdTHXWwInETfZOrb .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-bdTHXWwInETfZOrb .actor-man circle,#mermaid-svg-bdTHXWwInETfZOrb line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-bdTHXWwInETfZOrb :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
POST /login {username, password}
验证用户信息
返回JWT Token
GET /api/data (Header: Authorization: Bearer <token>)
验证Token
返回数据
7.2 JWT 实现
// JWT 工具类
@Component
public class JwtUtil {
@Value("${jwt.secret}")
private String secret;
public String generateToken(UserDetails userDetails) {
return Jwts.builder()
.setSubject(userDetails.getUsername())
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + 86400000))
.signWith(SignatureAlgorithm.HS256, secret)
.compact();
}
public boolean validateToken(String token, UserDetails userDetails) {
return extractUsername(token).equals(userDetails.getUsername())
&& !isTokenExpired(token);
}
}
// JWT 认证过滤器
public class JwtAuthenticationFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain chain) {
String token = extractToken(request);
if (token != null && jwtUtil.validateToken(token, userDetails)) {
UsernamePasswordAuthenticationToken auth =
new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(auth);
}
chain.doFilter(request, response);
}
}
八、常见场景解决方案
8.1 场景一:记住我功能
http
.rememberMe(remember -> remember
.key("unique-and-secret")
.tokenValiditySeconds(86400)
.userDetailsService(userDetailsService)
);
8.2 场景二:退出登录
http
.logout(logout -> logout
.logoutUrl("/logout")
.logoutSuccessUrl("/login?logout")
.deleteCookies("JSESSIONID")
.addLogoutHandler(new SecurityContextLogoutHandler())
);
8.3 场景三:CSRF 防护
http
.csrf(csrf -> csrf
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
// API接口可以禁用CSRF
.ignoringRequestMatchers("/api/**")
);
8.4 场景四:自定义登录页
http
.formLogin(form -> form
.loginPage("/login")
.defaultSuccessUrl("/dashboard")
.permitAll()
);
九、学习路线
#mermaid-svg-IxqcqUHT2aSVDiCU{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-IxqcqUHT2aSVDiCU .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-IxqcqUHT2aSVDiCU .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-IxqcqUHT2aSVDiCU .error-icon{fill:#552222;}#mermaid-svg-IxqcqUHT2aSVDiCU .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-IxqcqUHT2aSVDiCU .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-IxqcqUHT2aSVDiCU .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-IxqcqUHT2aSVDiCU .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-IxqcqUHT2aSVDiCU .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-IxqcqUHT2aSVDiCU .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-IxqcqUHT2aSVDiCU .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-IxqcqUHT2aSVDiCU .marker{fill:#333333;stroke:#333333;}#mermaid-svg-IxqcqUHT2aSVDiCU .marker.cross{stroke:#333333;}#mermaid-svg-IxqcqUHT2aSVDiCU svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-IxqcqUHT2aSVDiCU p{margin:0;}#mermaid-svg-IxqcqUHT2aSVDiCU .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-IxqcqUHT2aSVDiCU .cluster-label text{fill:#333;}#mermaid-svg-IxqcqUHT2aSVDiCU .cluster-label span{color:#333;}#mermaid-svg-IxqcqUHT2aSVDiCU .cluster-label span p{background-color:transparent;}#mermaid-svg-IxqcqUHT2aSVDiCU .label text,#mermaid-svg-IxqcqUHT2aSVDiCU span{fill:#333;color:#333;}#mermaid-svg-IxqcqUHT2aSVDiCU .node rect,#mermaid-svg-IxqcqUHT2aSVDiCU .node circle,#mermaid-svg-IxqcqUHT2aSVDiCU .node ellipse,#mermaid-svg-IxqcqUHT2aSVDiCU .node polygon,#mermaid-svg-IxqcqUHT2aSVDiCU .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-IxqcqUHT2aSVDiCU .rough-node .label text,#mermaid-svg-IxqcqUHT2aSVDiCU .node .label text,#mermaid-svg-IxqcqUHT2aSVDiCU .image-shape .label,#mermaid-svg-IxqcqUHT2aSVDiCU .icon-shape .label{text-anchor:middle;}#mermaid-svg-IxqcqUHT2aSVDiCU .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-IxqcqUHT2aSVDiCU .rough-node .label,#mermaid-svg-IxqcqUHT2aSVDiCU .node .label,#mermaid-svg-IxqcqUHT2aSVDiCU .image-shape .label,#mermaid-svg-IxqcqUHT2aSVDiCU .icon-shape .label{text-align:center;}#mermaid-svg-IxqcqUHT2aSVDiCU .node.clickable{cursor:pointer;}#mermaid-svg-IxqcqUHT2aSVDiCU .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-IxqcqUHT2aSVDiCU .arrowheadPath{fill:#333333;}#mermaid-svg-IxqcqUHT2aSVDiCU .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-IxqcqUHT2aSVDiCU .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-IxqcqUHT2aSVDiCU .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-IxqcqUHT2aSVDiCU .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-IxqcqUHT2aSVDiCU .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-IxqcqUHT2aSVDiCU .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-IxqcqUHT2aSVDiCU .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-IxqcqUHT2aSVDiCU .cluster text{fill:#333;}#mermaid-svg-IxqcqUHT2aSVDiCU .cluster span{color:#333;}#mermaid-svg-IxqcqUHT2aSVDiCU div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-IxqcqUHT2aSVDiCU .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-IxqcqUHT2aSVDiCU rect.text{fill:none;stroke-width:0;}#mermaid-svg-IxqcqUHT2aSVDiCU .icon-shape,#mermaid-svg-IxqcqUHT2aSVDiCU .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-IxqcqUHT2aSVDiCU .icon-shape p,#mermaid-svg-IxqcqUHT2aSVDiCU .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-IxqcqUHT2aSVDiCU .icon-shape rect,#mermaid-svg-IxqcqUHT2aSVDiCU .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-IxqcqUHT2aSVDiCU .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-IxqcqUHT2aSVDiCU .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-IxqcqUHT2aSVDiCU :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
Spring Security 入门
理解核心概念
认证机制
授权控制
JWT集成
OAuth2/SAML
微服务安全
实战项目
9.1 学习时间建议
| 入门 | 基本概念、配置 | 1周 |
| 进阶 | 认证授权、自定义 | 2周 |
| 高级 | JWT、OAuth2 | 2周 |
| 实战 | 项目应用 | 持续 |
十、最佳实践
10.1 密码加密
// 始终使用 BCrypt
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
10.2 权限设计原则
// 推荐:基于角色的权限访问控制 (RBAC)
@PreAuthorize("hasRole('ADMIN') and hasAuthority('user:delete')")
// 不推荐:硬编码
@PreAuthorize("hasRole('ADMIN') or username == 'admin'")
10.3 异常处理
@RestControllerAdvice
public class SecurityExceptionHandler {
@ExceptionHandler(AccessDeniedException.class)
public ResponseEntity<?> handleAccessDenied(AccessDeniedException e) {
return ResponseEntity.status(403)
.body("没有权限访问该资源");
}
}
10.4 安全配置
// 生产环境必须配置
http
.headers(headers -> headers
.contentSecurityPolicy(csp -> csp.policyDirectives("default-src 'self'"))
.frameOptions(frame -> frame.sameOrigin())
.httpStrictTransportSecurity(hsts -> hsts
.includeSubDomains(true)
.maxAgeInSeconds(31536000)
)
);
十一、总结
Spring Security 虽然学习曲线陡峭,但一旦掌握,将极大提升应用的安全性和开发效率。
11.1核心要点回顾
| 🔐 认证 | 验证用户身份 |
| 🎯 授权 | 控制访问权限 |
| 🔗 过滤器链 | 请求处理核心 |
| 🎫 JWT | 无状态认证方案 |
| 🛡️ 防护 | 抵御常见攻击 |
十二、推荐资源
| 官方文档 | https://spring.io/projects/spring-security |
| Baeldung教程 | https://www.baeldung.com/spring-security |
| 中文手册 | https://springcloud.cc/spring-security.html |
💡 一句话总结:Spring Security 是企业级 Java 应用的安全基石,值得深入学习和掌握!



