资讯动态

Spring Security认证机制详解

发布时间:2026/10/14 15:49:50 来源:尧图企业网站定制
Spring Security认证机制详解定位第 02 篇讲透认证三要素模型、UserDetailsService 体系、密码编码、完整认证流程与认证结果的落地适用版本Spring Security 6.xSpring Boot 3.x目录一、认证模型二、用户信息来源三、密码编码四、认证流程五、认证成功后的落地六、总结七、常见高频面试题一、认证模型1.1 三个核心抽象抽象角色Authentication认证令牌装凭证用户名/密码/Token、认证后的身份与权限AuthenticationManager认证入口接收 Authentication分发给合适的 ProviderAuthenticationProvider真正执行校验核对凭证产出已认证的 Authentication1.2 Authentication 的两态认证前未认证持有用户名 密码凭证authenticated false 认证后已认证持有主体UserDetails 权限凭证清除authenticated true同一个对象承载待验证材料与验证结果两种状态——认证成功后凭证密码被抹去避免在上下文中长期留存敏感信息。1.3 Provider 链AuthenticationManager默认ProviderManager持有多个 Provider依次尝试谁能处理该认证类型——这支撑了表单登录、JWT、LDAP 等多种认证方式共存。二、用户信息来源2.1 UserDetailsServicepublicinterfaceUserDetailsService{UserDetailsloadUserByUsername(Stringusername);}职责单一按用户名查用户。典型实现查数据库ServicepublicclassDbUserDetailsServiceimplementsUserDetailsService{publicUserDetailsloadUserByUsername(Stringusername){SysUseruuserMapper.findByUsername(username);// 查库if(unull)thrownewUsernameNotFoundException(username);returnUser.builder().username(u.getUsername()).password(u.getPassword())// 库中已是哈希.authorities(u.getRoles())// 权限/角色.build();}}2.2 UserDetails用户的安全视图用户名、密码、权限集合以及账号状态标志未过期、未锁定、凭证未过期、已启用——任一标志为 false 会抛对应异常拒绝登录。2.3 内置实现与选择实现场景内存用户演示/测试JDBC标准用户表结构自定义查库生产主流三、密码编码3.1 PasswordEncoderStringencode(CharSequencerawPassword);// 存储用booleanmatches(CharSequenceraw,Stringencoded);// 校验用3.2 BCrypt 与 Delegating编码器说明BCryptPasswordEncoder默认推荐加盐哈希每次结果不同盐随机暴力破解成本高DelegatingPasswordEncoderBoot 默认按密文前缀{bcrypt}/{sha256}路由到对应算法支持存量算法平滑升级3.3 纪律① 永不存明文密码 ② 不自行实现哈希盐/迭代次数有讲究 ③ 旧弱算法MD5/SHA1只用于兼容校验新密码一律强算法 ④ 登录失败信息不区分用户不存在与密码错误防枚举四、认证流程以表单登录为例的完整链路① UsernamePasswordAuthenticationFilter 从请求提取用户名/密码 ② 组装未认证的 UsernamePasswordAuthenticationToken ③ 交给 AuthenticationManagerProviderManager ④ DaoAuthenticationProvider 处理 UserDetailsService.loadUserByUsername 查用户 PasswordEncoder.matches 比对密码 校验账号状态锁定/过期/禁用 ⑤ 成功生成已认证 Authentication凭证清除、含权限 → SecurityContextHolder 存入 → 后续过滤器授权使用 ⑥ 失败抛 BadCredentialsException → ExceptionTranslationFilter → 401/登录页要点DaoAuthenticationProvider是表单登录的默认 Provider桥接 UserDetailsService 与 PasswordEncoder认证成功后Authentication里的主体就是UserDetails——业务代码取当前用户的来源认证是一次性动作后续请求靠会话/Token 恢复第五节。五、认证成功后的落地5.1 上下文建立与持久化认证成功 → SecurityContextHolder.setAuthentication(...)当前线程 → SecurityContextRepository 保存到会话表单登录场景 请求结束 → 上下文清理避免线程复用串用户5.2 后续请求的恢复下一个请求带会话或 Token → 安全上下文过滤器从仓库恢复 Authentication 到 Holder → 授权过滤器据此判定权限会话形态见 04 篇无状态 JWT 形态见 05 篇每次请求解析 Token 重建不存会话。六、总结三要素模型Authentication两态令牌、AuthenticationManager分发、AuthenticationProvider校验Provider 链支撑多认证方式共存。UserDetailsService按用户名查用户的单一职责接口生产实现查库返回 UserDetails含账号状态标志。密码编码BCrypt 加盐哈希是默认DelegatingPasswordEncoder 支持算法平滑升级不存明文、错误信息防枚举。认证流程过滤器提取凭证 → Token → ProviderManager → DaoAuthenticationProvider查用户 比密码 验状态→ 成功存上下文 / 失败 401。落地认证成功存 SecurityContextHolder 并持久化到会话或无状态化后续请求恢复上下文供授权使用。七、常见高频面试题1. Spring Security 的认证流程是怎样的要点以表单登录为例——认证过滤器提取用户名密码组装未认证的 AuthenticationUsernamePasswordAuthenticationToken交给 AuthenticationManagerProviderManager分发给 ProviderDaoAuthenticationProvider 通过 UserDetailsService 查用户、用 PasswordEncoder 比对密码、校验账号状态成功则生成已认证的 Authentication清除凭证、含权限存入 SecurityContextHolder失败抛异常经 ExceptionTranslationFilter 转 401/登录页。2. Authentication 对象包含什么为什么说有两态要点Authentication 是认证令牌承载凭证、主体身份与权限。两态认证前——持有用户名密码等凭证authenticatedfalse认证成功后——持有主体UserDetails与权限凭证被清除authenticatedtrue。同一对象既当待验证材料又当验证结果成功后清除凭证避免敏感信息长期留存。3. UserDetailsService 的作用怎么自定义要点按用户名加载用户的单一职责接口唯一方法 loadUserByUsername 返回 UserDetails。自定义实现生产主流注入数据访问层按用户名查库用户不存在抛 UsernameNotFoundException存在则用 User.builder 组装用户名、哈希密码、权限、账号状态。Spring 只用它取用户密码比对由 DaoAuthenticationProvider PasswordEncoder 完成。4. UserDetails 和自定义用户实体是什么关系要点UserDetails 是 Security 的用户安全视图——用户名、密码、权限集合、账号状态标志未过期/未锁定/凭证未过期/启用业务实体如 SysUser是领域模型含业务字段。关系UserDetailsService 负责把业务实体转换成 UserDetails或让实体实现 UserDetails。分离二者避免把领域模型直接暴露给安全框架。5. 密码为什么要用 BCrypt 存储DelegatingPasswordEncoder 解决什么要点明文存储泄露即全毁普通哈希可被彩虹表/暴力破解BCrypt 是加盐慢哈希——每次加密结果不同随机盐内置于密文、计算成本高抗暴力破解。DelegatingPasswordEncoder 按密文前缀{bcrypt}、{sha256}路由到对应算法让系统能校验存量旧算法密码同时新密码用更强算法——支持算法平滑升级而不强制全员改密。6. DaoAuthenticationProvider 做了什么要点表单/Basic 认证的核心 Provider桥接三个部件调 UserDetailsService.loadUserByUsername 获取用户用 PasswordEncoder.matches 比对提交密码与库中哈希校验账号状态锁定/过期/禁用抛对应异常。全部通过则产出已认证 Authentication。它是默认注册的 Provider自定义认证方式时新增自己的 Provider 与其并列。7. 认证成功后用户信息存在哪业务代码怎么取当前用户要点存入 SecurityContextHolder默认 ThreadLocal 的 SecurityContext。业务代码取当前用户SecurityContextHolder.getContext().getAuthentication().getPrincipal()通常是 UserDetails控制器方法可直接注入 Authentication/Principal 参数模板层有 sec 标签。注意异步线程默认拿不到上下文不跨线程需传递或配置继承策略。8. 登录失败时为什么不能提示用户不存在要点区分用户不存在与密码错误会帮助攻击者枚举有效用户名账号探测。安全做法两者统一返回用户名或密码错误且响应时间尽量一致对不存在的用户也做一次哈希比对防时间侧信道。同理登录要有失败次数与锁定防暴力破解。9. 多种认证方式表单 JWT Basic如何共存要点ProviderManager 持有多个 AuthenticationProvider按顺序尝试处理对应的 Authentication 类型不同认证过滤器表单、Basic、自定义 JWT 过滤器各自提取凭证组装对应的 Token 交给 Manager。也可用多条 SecurityFilterChain 按路径分开配置。共存的关键是过滤器负责提取Provider 负责校验的职责分离。10. 认证和授权在流程上是什么关系要点先后关系且数据传递。认证先执行——确定你是谁产出含权限的 Authentication 存入安全上下文授权随后——从上下文读取身份与权限按规则角色/权限/表达式判定你能否访问。没有认证就没有授权依据认证失败401与授权失败403是不同阶段的不同异常。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑