news 2026/7/10 12:48:58

Spring Security 认证流程闭环与调用链路详解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Spring Security 认证流程闭环与调用链路详解

书 接 上 回、我 们 分 析 下 AuthController.@PostMapping("/login") 接 口 作 为 切 入 点 进 行 深 入 浅 出 剖 析 ~ ~

下 面 我 们 以 小 明 的 authenticateUser 方 法 为 入 口 , 详 细 拆 解 认 证 执 行 的 ** 完 整 流 程 闭 环 ** , 并 深 入 分 析 Authentication authentication = authenticationManager.authenticate(...) 的 ** 调 用 链 路 ** , 同 时 说 明 ** 自 定 义 类 ** 在 其 中 的 作 用 。 代 码 块 中 汉 字 正 常 书 写 , 代 码 块 外 汉 字 间 保 持 2 个 空 格 。

一 、 完 整 认 证 流 程 闭 环

认 证 流 程 从 用 户 提 交 登 录 请 求 开 始 , 到 返 回 JWT 响 应 结 束 , 形 成 如 下 闭 环 :

用户提交登录请求

接收LoginRequest参数

创建UsernamePasswordAuthenticationToken

调用AuthenticationManager.authenticate

DaoAuthenticationProvider处理认证

UserDetailsService查询用户

PasswordEncoder验证密码

构建认证后Authentication对象

设置SecurityContextHolder

JwtService生成JWT令牌

封装JwtResponse响应

返回响应给用户

流 程 闭 环 详 细 步 骤 ( 结 合 代 码 )

1. 接 收 登 录 请 求 ( 自 定 义 DTO 入 口 )

用 户 通 过 前 端 提 交 用 户 名 和 密 码 , 请 求 体 被 @RequestBody LoginRequest loginRequest 接 收 。

** 自 定 义 类 LoginRequest 作 用 ** : 封 装 登 录 请 求 参 数 ( 用 户 名 、 密 码 ) , 代 码 如 下 :

public class LoginRequest {

private String username; // 用 户 名

private String password; // 密 码

// Getters and Setters

}

2. 创 建 认 证 请 求 对 象 ( Spring Security 自 带 类 )

通 过 new UsernamePasswordAuthenticationToken(loginRequest.getUsername(), loginRequest.getPassword()) 创 建 认 证 请 求 对 象 。

** Spring Security 自 带 类 UsernamePasswordAuthenticationToken 作 用 ** :

来 源 : org.springframework.security.authentication.UsernamePasswordAuthenticationToken

作 用 : 封 装 用 户 名 密 码 认 证 请 求 , 初 始 状 态 下 authorities ( 权 限 ) 为 空 , 相 当 于 “ 未 盖 章 的 通 行 证 ” 。

3. 调 用 AuthenticationManager.authenticate() ( 核 心 调 用 链 路 , 下 文 详 解 )

将 上 述 UsernamePasswordAuthenticationToken 传 入 authenticationManager.authenticate() , 触 发 认 证 流 程 。

4. 认 证 成 功 后 设 置 安 全 上 下 文

认 证 成 功 返 回 填 充 完 权 限 的 Authentication 对 象 , 通 过 SecurityContextHolder.getContext().setAuthentication(authentication) 绑 定 到 当 前 线 程 。

5. 生 成 JWT 令 牌 ( 自 定 义 JwtService )

调 用 jwtService.generateToken(authentication) 生 成 JWT , 用 于 后 续 无 状 态 认 证 。

** 自 定 义 类 JwtService 作 用 ** : 封 装 JWT 生 成 / 验 证 逻 辑 , 核 心 方 法 generateToken(Authentication authentication) 从 authentication 中 提 取 用 户 名 、 权 限 等 信 息 , 按 规 则 生 成 签 名 令 牌 。

6. 封 装 响 应 数 据 ( 自 定 义 DTO )

从 authentication.getPrincipal() 获 取 UserDetailsImpl ( 自 定 义 用 户 详 情 类 ) , 提 取 用 户 ID 、 用 户 名 、 邮 箱 、 角 色 等 信 息 , 封 装 为 JwtResponse 返 回 。

** 自 定 义 类 作 用 ** :

UserDetailsImpl : 实 现 Spring Security 的 UserDetails 接 口 , 封 装 用 户 基 础 信 息 ( ID 、 用 户 名 、 邮 箱 ) 和 权 限 ( 角 色 / 权 限 字 符 串 ) , 代 码 示 例 :

public class UserDetailsImpl implements UserDetails {

private Long id;

private String username;

private String email;

private String password;

private Collection<? extends GrantedAuthority> authorities;

// 实现UserDetails接口方法(getAuthorities()等)

// Getters and Setters

}

JwtResponse : 封 装 JWT 响 应 数 据 ( token 、 用 户 ID 、 用 户 名 、 邮 箱 、 角 色 列 表 ) , 代 码 示 例 :

public class JwtResponse {

private String token;

private Long id;

private String username;

private String email;

private List<String> roles;

// Constructor, Getters and Setters

}

7. 返 回 响 应 与 异 常 处 理

认 证 成 功 返 回 ResponseEntity.ok(response) ; 失 败 ( 如 密 码 错 误 ) 捕 获 BadCredentialsException , 返 回 401 错 误 。

二 、 AuthenticationManager.authenticate(...) 调 用 链 路 详 解

这 段 代 码 是 认 证 流 程 的 ** 核 心 枢 纽 ** , 其 内 部 调 用 链 路 如 下 :

调 用 链 路 示 意 图

authenticationManager.authenticate(token)

AuthenticationManager ( 接 口 , 默 认 实 现 ProviderManager )

↓ 遍 历 注 册 的 AuthenticationProvider , 找 到 支 持 UsernamePasswordAuthenticationToken 的 Provider

DaoAuthenticationProvider ( Spring Security 自 带 , 处 理 用 户 名 密 码 认 证 )

↓ 调 用 UserDetailsService.loadUserByUsername(username) ( 自 定 义 实 现 )

UserServiceImpl ( 自 定 义 , 实 现 UserDetailsService )

↓ 从 数 据 库 查 询 用 户 信 息 , 封 装 为 UserDetailsImpl 返 回

DaoAuthenticationProvider

↓ 用 PasswordEncoder.matches(rawPassword, encodedPassword) 验 证 密 码

PasswordEncoder ( 自 定 义 BCryptPasswordEncoder )

↓ 验 证 通 过 , 构 建 已 认 证 Authentication 对 象

new UsernamePasswordAuthenticationToken(principal, credentials, authorities)

↓ 返 回 给 authenticationManager.authenticate()

Authentication ( 认 证 成 果 )

链 路 关 键 环 节 注 释

1. AuthenticationManager : 认 证 总 调 度 员

** 来 源 ** : Spring Security 核 心 接 口 org.springframework.security.authentication.AuthenticationManager , 默 认 实 现 为 ProviderManager 。

** 作 用 ** : 接 收 Authentication 认 证 请 求 , 协 调 多 个 AuthenticationProvider ( 认 证 提 供 者 ) 完 成 认 证 。

** 入 参 ** : 未 认 证 的 UsernamePasswordAuthenticationToken ( 含 用 户 名 、 明 文 密 码 ) 。

** 出 参 ** : 认 证 成 功 后 的 Authentication 对 象 ( 含 用 户 详 情 、 权 限 集 合 ) 。

2. DaoAuthenticationProvider : 认 证 执 行 者 ( Spring Security 自 带 )

** 来 源 ** : org.springframework.security.authentication.dao.DaoAuthenticationProvider 。

** 作 用 ** : 处 理 用 户 名 密 码 认 证 的 具 体 逻 辑 , 依 赖 UserDetailsService 和 PasswordEncoder 。

** 核 心 步 骤 ** :

a. 调 用 UserDetailsService.loadUserByUsername(username) 查 询 用 户 ;

b. 用 PasswordEncoder 比 对 明 文 密 码 与 数 据 库 中 的 加 密 密 码 ;

c. 验 证 通 过 后 , 构 建 已 认 证 的 UsernamePasswordAuthenticationToken ( 填 充 authorities 权 限 ) 。

3. UserDetailsService : 用 户 信 息 查 询 器 ( 自 定 义 实 现 )

** 来 源 ** : Spring Security 核 心 接 口 org.springframework.security.core.userdetails.UserDetailsService 。

** 自 定 义 实 现 类 UserServiceImpl 作 用 ** : 从 数 据 库 查 询 用 户 信 息 , 封 装 为 UserDetails 对 象 ( 此 处 为 UserDetailsImpl ) 返 回 。

** 核 心 方 法 ** :

@Override

public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

// 1. 从数据库查询用户(自定义User实体类)

User user = userRepository.findByUsername(username)

.orElseThrow(() -> new UsernameNotFoundException("用户不存在"));

// 2. 封装为UserDetailsImpl(含权限)

return UserDetailsImpl.build(user);

}

4. PasswordEncoder : 密 码 验 证 器 ( 自 定 义 配 置 )

** 来 源 ** : Spring Security 核 心 接 口 org.springframework.security.crypto.password.PasswordEncoder , 此 处 用 自 定 义 BCryptPasswordEncoder 。

** 作 用 ** : 验 证 明 文 密 码 与 数 据 库 中 BCrypt 加 密 密 码 是 否 匹 配 。

** 调 用 代 码 ** :

if (!passwordEncoder.matches(loginRequest.getPassword(), userDetails.getPassword())) {

throw new BadCredentialsException("用户名或密码错误");

}

5. 构 建 认 证 后 Authentication 对 象

认 证 通 过 后 , DaoAuthenticationProvider 创 建 ** 已 认 证 ** 的 UsernamePasswordAuthenticationToken :

// 参数:principal=用户详情(UserDetailsImpl),credentials=null(密码已清空),authorities=用户权限

new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());

三 、 自 定 义 类 在 流 程 中 的 核 心 作 用 总 结

** 自 定 义 类 ** ** 作 用 描 述 ** ** 关 键 方 法 / 属 性 **

LoginRequest 封 装 登 录 请 求 参 数 ( 用 户 名 、 密 码 ) getUsername() 、 getPassword()

UserDetailsImpl 实 现 UserDetails 接 口 , 封 装 用 户 详 情 ( ID 、 用 户 名 、 邮 箱 、 权 限 ) getAuthorities() ( 返 回 权 限 集 合 ) 、 getUsername()

UserServiceImpl 实 现 UserDetailsService , 从 数 据 库 查 询 用 户 并 封 装 为 UserDetailsImpl loadUserByUsername(String username)

JwtService 生 成 / 验 证 JWT 令 牌 , 封 装 JWT 算 法 逻 辑 generateToken(Authentication authentication)

JwtResponse 封 装 JWT 响 应 数 据 ( token 、 用 户 信 息 、 角 色 ) token 、 id 、 roles

💡 小 明 的 流 程 体 会

认 证 流 程 闭 环 像 一 场 “ 身 份 验 证 演 习 ” :

用 户 递 交 “ 身 份 申 请 ” ( LoginRequest ) ;

框 架 发 放 “ 临 时 通 行 证 ” ( UsernamePasswordAuthenticationToken ) ;

“ 认 证 官 ” ( AuthenticationManager ) 调 度 “ 审 查 员 ” ( DaoAuthenticationProvider ) ;

“ 审 查 员 ” 查 阅 “ 档 案 库 ” ( UserServiceImpl 查 数 据 库 ) , 用 “ 密 码 对 比 仪 ” ( PasswordEncoder ) 验 证 ;

通 过 后 发 放 “ 正 式 身 份 证 ” ( 认 证 后 Authentication ) , 存 入 “ 工 作 台 ” ( SecurityContextHolder ) ;

最 后 制 作 “ 长 期 通 行 证 ” ( JWT ) 返 还 用 户 。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/9 14:31:19

什么叫组团社,什么叫地接社

在旅游行业中&#xff0c;有两个重要的角色&#xff1a;组团社与地接社&#xff0c;它们分别承担着不同的职责。 组团社&#xff0c;也被称为国内旅游批发商&#xff0c;其主要功能是接受旅游团或海外旅行社的预订。 它们负责制定并下达接待计划&#xff0c;甚至可以提供全程陪…

作者头像 李华
网站建设 2026/7/9 19:11:12

8大关键技术点掌握YashanDB的使用技巧

如何优化查询速度是数据库系统设计和运维中的重要问题&#xff0c;影响着业务响应时间和系统吞吐能力。高效的数据存储、合理的索引设计、智能的执行计划生成以及高并发事务控制技术&#xff0c;均直接关系到查询性能表现。本文围绕YashanDB数据库系统&#xff0c;深入剖析其八…

作者头像 李华
网站建设 2026/7/10 10:29:57

Kubernetes Service 架构深度解析:从虚拟IP到流量的智能寻址

在Kubernetes中&#xff0c;Pod间的直接互联仅是服务通信的基础。要构建一个稳定、弹性且对消费端透明的服务网络&#xff0c;其核心在于Service抽象层。许多开发者对Service的理解仅停留在“一个虚拟IP”的层面&#xff0c;却未能洞悉其背后精妙的流量治理机制&#xff1a;请求…

作者头像 李华
网站建设 2026/7/10 10:45:14

一个免费的在线拼图工具Collaigo

创作背景在社交媒体时代&#xff0c;无论是个人分享生活点滴&#xff0c;还是品牌运营社交媒体账号&#xff0c;拼贴图都成为了内容创作的重要形式。然而&#xff0c;我在使用现有工具时遇到了不少痛点&#xff1a;功能限制&#xff1a;很多工具只能做简单的网格拼图&#xff0…

作者头像 李华
网站建设 2026/7/10 0:19:48

【学习心得】Python好库推荐——pyttsx3

pyttsx3&#xff08;Python Text-to-Speech eXtended version 3&#xff09;是一个跨平台的 Python 库&#xff0c;用于将文本转换为语音&#xff08;Text-to-Speech, TTS&#xff09;。它可以在不依赖互联网连接的情况下&#xff0c;在本地将文本朗读出来&#xff0c;支持 Win…

作者头像 李华
网站建设 2026/7/10 9:12:12

Linux 通用软件包 AppImage 打包详解

格式介绍 - AppImageAppImage 是 Linux 系统中一种新型的软件包格式&#xff0c;它与 rpm、deb 这些软件包格式相比最大的不同便是&#xff1a;&#xff08;1&#xff09;无需安装&#xff0c;即用即删。&#xff08;2&#xff09;只需打包一次&#xff0c;便可到处运行。完美的…

作者头像 李华