Java中UsernamePasswordAuthenticationToken使用及代码解析
解析UsernamePasswordAuthenticationToken的这段代码实现
先看你给出的代码:
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken( userDetails, null, userDetails == null ? List.of() : userDetails.getAuthorities() );
这段代码的核心是构造一个已完成认证的Spring Security Authentication对象,下面逐个拆解你关心的点:
1. userDetails参数的作用
userDetails是Spring Security用来封装用户核心信息的标准对象,里面包含了用户名、加密后的密码、用户权限、账号状态(是否锁定、过期、禁用等)。这里把它作为Authentication的principal(主体)传入,后续这个对象会被存入SecurityContextHolder,业务代码里可以通过SecurityContextHolder.getContext().getAuthentication().getPrincipal()获取当前登录用户的完整信息。
2. 传入null作为凭证(credentials)的原因
这里的credentials指的是用户的登录凭证(通常是密码)。传入null是Spring Security的标准实践:
- 认证完成后,密码已经完成了校验使命,继续保留会有敏感信息泄露的风险(比如被序列化、日志打印)。
- 已认证的Authentication对象不需要再携带凭证,Spring Security内部会通过
isAuthenticated()状态来判断认证状态,而非凭证是否存在。
3. 权限设置的逻辑
这个三元表达式是典型的空安全处理,目的是保证Authentication对象始终持有合法的权限集合:
- 当
userDetails为null时(比如认证失败、用户不存在的极端场景),用List.of()生成一个空的不可变权限列表,避免因为权限集合为null导致后续权限校验时抛出空指针异常。 - 当
userDetails有效时,调用userDetails.getAuthorities()获取用户的权限集合(比如ROLE_ADMIN、ROLE_USER这类GrantedAuthority实例),这些权限会用于后续的接口访问控制、方法级权限校验(比如@PreAuthorize注解)。 - 使用
List.of()是因为它返回的是不可变列表,能防止后续代码意外修改权限集合,保证权限信息的安全性和稳定性。
补充说明
这段代码一般出现在认证成功后的流程里:比如用户名密码校验通过后,用查询到的userDetails构造已认证的Authentication对象,再存入SecurityContextHolder,这样后续的请求就能自动识别当前用户的身份和权限。
内容的提问来源于stack exchange,提问作者badr ahrir
相关产品推荐
相关产品推荐

