手动认证关键代码逐行解析
手动认证关键代码逐行解析
UsernamePasswordAuthenticationToken authToken =
new UsernamePasswordAuthenticationToken(
userDetails, // ① principal
null, // ② credentials
userDetails.getAuthorities()); // ③ authorities
authToken.setDetails(
new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authToken);
1️⃣ UsernamePasswordAuthenticationToken 构造器
| 参数 | 含义 | 常见取值 |
| --------------- | --------------------- | ------------------------------ |
| principal | 认证主体(谁) | 自定义 UserDetails 实例 |
| credentials | 登录凭证(密码/令牌) | 手动认证时通常设为 null |
| authorities | 权限集合 | userDetails.getAuthorities() |
2️⃣ setDetails(...):补充请求级元数据
-
由
WebAuthenticationDetailsSource.buildDetails(request)生成 -
默认包含:
-
remoteAddress(客户端 IP) -
sessionId(当前会话 ID)
-
-
可用于审计、IP 白名单、自定义
AccessDecisionVoter
3️⃣ SecurityContextHolder.getContext().setAuthentication(...)
-
将认证令牌放入 当前线程 的
SecurityContext -
默认实现:
ThreadLocalSecurityContextHolderStrategy -
请求结束后由
SecurityContextPersistenceFilter保存到HttpSession,实现“登录状态保持”
典型使用场景
| 场景 | 触发点 |
| ------------ | --------------------------------------- |
| JWT 登录 | 自定义过滤器解析完 JWT 后手动建立上下文 |
| SSO / OAuth2 | 外部系统已认证,本地仅做上下文同步 |
| 单元测试 | 快速模拟已登录用户 |
注意事项清单
-
✅ 线程安全:异步任务需手动传递或清空
SecurityContext -
✅ 密码擦除:手动认证时把
credentials设为null -
✅ Session 固定攻击:登录后调用
changeSessionId() -
✅ 并发会话控制:手动登录后需同步
SessionRegistry
一句话总结:告诉 Spring Security —— “此请求已认证,用户是 XXX,权限是 [ROLE_A, ROLE_B],请放行”。
本文由萧兮的博客原创发布,欢迎转载,转载务必保留原文链接。
萧兮的博客:https://www.20010515.xyz · 原文:https://www.20010515.xyz/posts/87bdaa2e-5595-4adb-9040-79d72f09090d