先看一下UserDetails的源码和实现结构
public interface UserDetails extends Serializable {
Collection<? extends GrantedAuthority> getAuthorities();
String getPassword();
String getUsername();
boolean isAccountNonExpired();
boolean isAccountNonLocked();
boolean isCredentialsNonExpired();
boolean isEnabled();
}
该类文档注释中有这么一段话:
提供用户核心信息。
Spring Security不直接使用实现来实现安全性。它们只是存储稍后封装到Authentication对象中的用户信息。这使得与安全无关的用户信息(如电子邮件地址、电话号码等)可以存储在一个方便的位置。
那这句话什么意思呢?
- 该接口是提供用户信息的核心接口。
- 该接口实现仅仅存储用户的信息。
- 后续会将该接口提供的用户信息封装到认证对象中去。
那UserDetails默认提供的方法都是什么意思呢?
1.Collection<? extends GrantedAuthority> getAuthorities();
用户的权限集, 默认需要添加前缀
2.String getPassword();
用户的加密后的密码, 不加密会使用前缀
3.String getUsername();
应用内唯一的用户名
4.boolean isAccountNonExpired();
账户是否过期
5.boolean isAccountNonLocked();
账户是否锁定
6.boolean isCredentialsNonExpired();
凭证是否过期
7.boolean isEnabled();
用户是否可用
它和Authentication接口很类似,比如它们都拥有username,authorities。Authentication的getCredentials()与 UserDetails中的getPassword()需要被区分对待,前者是用户提交的密码凭证,后者是用户实际存储的密码(数据库中的密码),认证其实就是对这两者的比对。Authentication中的getAuthorities()实际是由UserDetails的getAuthorities()传递而形成的。还记得Authentication接口中的getDetails()方法吗?其中的UserDetails用户详细信息便是经过了 AuthenticationProvider认证之后被填充的。
在实际开发中,如果以上的信息满足不了你使用(通常是满足不了的),你可以自行实现扩展以存储更多的用户信息。比如用户的邮箱、手机号等等。也就是说咱们可以自己去实现这个接口,然后在其基础上,加上自己想要的属性,下面给个示例:
package com.itheima.stock.security.detail;
import com.itheima.stock.pojo.vo.PermissionRespNodeVo;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import java.util.List;
/**
* @author Mr.huang
* @version 1.0
* @description 自定义用户认证详情类
* @date 2023/2/9 9:16
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class LoginUserDetail implements UserDetails {
/*
用户密码
*/
private String password;
// @Override
// public String getPassword() {
// return null;
// }
/*
用户名
*/
private String username;
// @Override
// public String getUsername() {
// return null;
// }
/*
权限信息
*/
private List<GrantedAuthority> authorities;
// @Override
// public Collection<? extends GrantedAuthority> getAuthorities() {
// return null;
// }
/*
账户是否过期
*/
private boolean isAccountNonExpired=true;
// @Override
// public boolean isAccountNonExpired() {
// return false;
// }
/*
账号是否被锁定
true 没有被锁定
*/
private boolean isAccountNonLocked=true;
// @Override
// public boolean isAccountNonLocked() {
// return false;
// }
/*
密码是否过期
true 没有过期
*/
private boolean isCredentialsNonExpired=true;
// @Override
// public boolean isCredentialsNonExpired() {
// return false;
// }
/*
账户是否禁用
true:没有禁用
*/
private boolean isEnabled=true;
// @Override
// public boolean isEnabled() {
// return false;
// }
/**
* 用户ID
*/
private String id;
/**
* 电话
*/
private String phone;
/**
* 昵称
*/
private String nickName;
/**
* 真实姓名
*/
private String realName;
/**
* 性别(1.男 2.女)
*/
private Integer sex;
/**
* 账户状态(1.正常 2.锁定 )
*/
private Integer status;
/**
* 邮箱
*/
private String email;
/**
* 权限树,不包含按钮相关权限信息
*/
private List<PermissionRespNodeVo> menus;
/**
* 按钮权限集合
*/
private List<String> permissions;
}
那这个类会用到哪里呢?
当 UserDetailsService 调用UserDetails loadUserByUsername(String loginName)方法时
这个方法会根据用户名提取用户信息 UserDetails(包含密码) ,一般是从数据库中提取信息进行组装,最后返回一个UserDetails实例.loadUserByUsername方法返回之后的UserDetails就去和 Authentication中的数据做认证并传递数据,形成认证之后的Authentication,即successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult)方法中的Authentication!
如果这篇文章对您有帮助,请动动你的小手指,点个关注和赞!,鼓励鼓励作者