【Spring Security】 登录核心类
【Spring Security】 登录核心类
Metadata
title: 【Spring Security】 登录核心类
date: 2023-02-02 11:51
tags:
- 行动阶段/完成
- 主题场景/组件
- 笔记空间/KnowladgeSpace/ProgramSpace/ModuleSpace
- 细化主题/Module/SpringSecurity
categories:
- SpringSecurity
keywords:
- SpringSecurity
description: 【Spring Security】 登录核心类
【Spring Security】 登录核心类
[[【Spring Security】 用户 密码 认证]]中我们分析了表单登录的基本流程,接下来分析下使用到的核心类。
UserDetails
UserDetails 翻译过来是用户详情的意思,它是一个接口,主要提供了保存用户信息的功能,登录时会查询数据库,封装 UserDetails 的子类实体,然后进行状态、密码等认证。
/**
* 提供核心用户信息。出于安全目的,Spring Security 不直接使用实现。
* 它们只是存储用户信息,然后将这些信息封装到 {@link Authentication} 对象中。
* 这允许将非安全相关的用户信息(例如电子邮件地址、 电话号码等)存储在方便的位置。
* 具体实现必须特别小心,以确保强制执行每个方法的详细非空契约。
*/
public interface UserDetails extends Serializable {
/**
* 返回授予用户的权限
*/
Collection<? extends GrantedAuthority> getAuthorities();
/**
* 返回用于验证用户的密码
*/
String getPassword();
/**
* 返回用于验证用户的用户名
*/
String getUsername();
/**
* 指示用户的帐户是否已过期。过期的帐户无法进行身份验证
*/
boolean isAccountNonExpired();
/**
* 指示用户是被锁定还是未锁定。 无法对锁定的用户进行身份验证
*/
boolean isAccountNonLocked();
/**
* 指示用户的凭据(密码)是否已过期。过期的凭据会阻止身份验证
*/
boolean isCredentialsNonExpired();
/**
* 指示用户是启用还是禁用。无法对禁用的用户进行身份验证
*/
boolean isEnabled();
}
User
Security 中的 User 类,就是实际存储用户认证信息的模型了,它实现了 UserDetails 及 CredentialsContainer 接口,提供了有参构造,根据用户名、密码、权限集合、过期禁用等状态构造认证用户模型。还提供了 builder 构造模式来创建 User 类。我们可以直接使用此类或者继承它来实现用户信息封装。
1. 登录后如何获取 User 信息
可以从 SecurityContext 中获取
SecurityContext context = SecurityContextHolder.getContext();
Authentication authentication = context.getAuthentication();
User principal = (User)authentication.getPrincipal();
可以看出,登录后,对密码进行了设置 null 处理,User 中没有保存。
2. 扩展 User 信息
User 只包含了用户名、权限、状态等信息,某些情况下,我们需要其他额外信息,比如部门 ID、登录时间等,这时可以扩展这个 User 类。
- 自定义用户类,继承 User 类。
public class MyUser extends User {
// 部门ID
Integer deptId;
// 登录时间
Date LoginTime;
// 调用父类构造
public MyUser(String username, String password, Collection<? extends GrantedAuthority> authorities) {
super(username, password, authorities);
}
public Integer getDeptId() {
return deptId;
}
public void setDeptId(Integer deptId) {
this.deptId = deptId;
}
public Date getLoginTime() {
return LoginTime;
}
public void setLoginTime(Date loginTime) {
LoginTime = loginTime;
}
}
- UserDetailsService 返回自定义用户类,并设置扩展信息。
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
// 1. 数据库查询用户
User user = userService.getUserByName(username);
if (user == null) {
throw new UsernameNotFoundException("用户名不存在!");
}
// 2. 设置权限集合,后续需要数据库查询
List<GrantedAuthority> authorityList =
AuthorityUtils.commaSeparatedStringToAuthorityList("role");
// 3. 返回自定义的用户信息
MyUser myUser = new MyUser(user.getUserName(), user.getPassword(), authorityList);
// 4. 设置自定义扩展信息
myUser.setDeptId(user.getOrganizationId());
myUser.setLoginTime(new Date());
return myUser;
}
DaoAuthenticationProvider
DaoAuthenticationProvider 是一种 AuthenticationProvider,利用 UserDetailsService 和 PasswordEncoder 来验证用户名和密码的实现。
让我们来看看 DaoAuthenticationProvider 在 Spring Security 中是如何工作的。
- Filter 从读取用户名和密码的身份验证传递 UsernamePasswordAuthenticationToken 到由 AuthenticationManager 实现 ProviderManager。
- 在 ProviderManager 被配置为使用一个的 AuthenticationProvider 类型的 DaoAuthenticationProvider。
- DaoAuthenticationProvider 中查找 UserDetails 从 UserDetailsService。
- DaoAuthenticationProvider 然后使用 PasswordEncoder 验证 UserDetails 上一步返回的密码。
- 当身份验证成功时,Authentication 返回的 是类型 UsernamePasswordAuthenticationToken 并且具有 UserDetails 由配置的返回的主体 UserDetailsService。最终,返回的值 UsernamePasswordAuthenticationToken 将由 SecurityContextHolderauthentication 设置 Filter。
WebSecurityConfigurerAdapter 及 PasswordEncoder 后续专题介绍。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 蝶梦庄生!
评论