一个请求是如何被处理的
首先我们知道security框架本身就是通过一堆的filter 过滤器来实现的,所以我们只要到特定的过滤器上看,就能找到相关核心组件,并进行二次开发。
几个核心组件
SecurityContextHolder
Spring Security 身份验证模型的核心是 SecurityContextHolder,它包含 SecurityContext。
SecurityContext
SecurityContext 是从 SecurityContextHolder 获得的,它包含一个 Authentication 对象。
Authentication
Authentication是一个认证对象。在Authentication接口中声明了如下的相关方法。
public interface Authentication extends Principal, Serializable {
// 获取认证用户拥有的对应的权限
Collection<? extends GrantedAuthority> getAuthorities();
// 获取哦凭证
Object getCredentials();
// 存储有关身份验证请求的其他详细信息。这些可能是 IP地址、证书编号等
Object getDetails();
// 获取用户信息 通常是 UserDetails 对象
Object getPrincipal();
// 是否认证
boolean isAuthenticated();
// 设置认证状态
void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException;
}
基于上面讲的三个组件,我们可以在项目中获取当前用户的登录信息了
public String hello(){
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
Object principal = authentication.getPrincipal();
if(principal instanceof UserDetails){
UserDetails userDetails = (UserDetails) principal;
System.out.println(userDetails.getUsername());
return "当前登录的账号是:" + userDetails.getUsername();
}
return "当前登录的账号-->" + principal.toString();
}
UserDetailsService
在上面的关系中我们看到在Authentication中存储当前登录用户的是Principal对象,而通常情况下Principal对象可以转换为UserDetails对象。UserDetails是Spring Security中的一个核心接口。它表示一个principal,但是是可扩展的、特定于应用的。
AuthenticationManager
AuthenticationManager 是定义 Spring 安全过滤器如何执行身份验证的 API。
ProviderManager
ProviderManager 是 AuthenticationManager 最常用的实现。
AuthenticationProvider
可以将多个 AuthenticationProvider 注入 ProviderManager。每个 AuthenticationProvider 执行特定类型的身份验证。例如,DauAuthenticationProvider 支持基于用户名/密码的身份验证,而 JwtAuthenticationProvider 支持对 JWT 令牌进行身份验证。
AbstractAuthenticationProcessingFilter
当用户提交凭据时
接下来,身份验证被传递到 AuthenticationManager 以进行身份验证
如果身份验证失败,则为“失败”
如果身份验证成功,则为“成功”。
自定义认证
如下我们只需要实现 UserDetailsService 接口,spring就会自动注入我们的认证方法(可以引入其他存储中间件做替换)
@Service
public class CustomUserDetailsServiceImpl implements UserDetailsService{
@Autowired
private UserMapper userMapper;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
// 模拟jdbc获取用户信息
User user = userMapper.getByUserName(username);
String userNameJdbc = user.getUserName();
String userPasswordJdbc = user.getPassWord();
if(userNameJdbc.equals(username)){
List<SimpleGrantedAuthority> authorities = new ArrayList<>();
// 设置登录角色
authorities.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
UserDetails userDetails = new User(userNameJdbc,userPasswordJdbc,authorities);
return userDetails;
}
throw new UsernameNotFoundException("用户不存在");
}
}