public TokenVo login(String username, String password) {
//封装 Authentication
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username, password);
//认证用户
Authentication authenticate = authenticationManager.authenticate(authenticationToken);
if (authenticate == null) {
throw new RuntimeException("认证失败!");
}
//获取认证用户信息
UserDetailsInfo userDetailsInfo = (UserDetailsInfo) authenticate.getPrincipal();
//认证通过,生成jwt
TokenVo tokenVo=new TokenVo();
String token = jwtTokenUtil.generateToken(userDetailsInfo);
tokenVo.setToken(token);
tokenVo.setExpireTime(jwtTokenUtil.expiration);
redisCache.setCacheObject(token, userDetailsInfo, jwtTokenUtil.expiration, TimeUnit.SECONDS);
return tokenVo;
}
authenticationManager.authenticate(authenticationToken);
其所属类是ProviderManager implements AuthenticationManage
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
Class<? extends Authentication> toTest = authentication.getClass();
AuthenticationException lastException = null;
AuthenticationException parentException = null;
Authentication result = null;
Authentication parentResult = null;
int currentPosition = 0;
int size = this.providers.size();
// 遍历所有的验证提供者
for (AuthenticationProvider provider : getProviders()) {
// 判断当前验证提供者是否支持传入的Authentication对象的类型
if (!provider.supports(toTest)) {
continue;
}
// 打印正在使用的验证提供者和当前位置
logger.trace(LogMessage.format("Authenticating request with %s (%d/%d)",
provider.getClass().getSimpleName(), ++currentPosition, size));
try {
// 调用当前验证提供者的authenticate方法进行身份验证
result = provider.authenticate(authentication);
// 如果验证成功,复制验证结果的详细信息到原始的Authentication对象中
if (result != null) {
//copyDetails(authentication, result);
break;
}
} catch (AccountStatusException | InternalAuthenticationServiceException ex) {
// 准备抛出异常并中止验证过程
prepareException(ex, authentication);
throw ex;
} catch (AuthenticationException ex) {
lastException = ex;
}
}
// 如果当前验证提供者未能验证成功,并且存在父验证管理器,则尝试使用父验证管理器进行验证
if (result == null && this.parent != null) {
try {
parentResult = this.parent.authenticate(authentication);
result = parentResult;
} catch (ProviderNotFoundException ex) {
// 忽略该异常
} catch (AuthenticationException ex) {
parentException = ex;
lastException = ex;
}
}
// 如果验证成功,执行一些后续操作,如擦除验证结果中的敏感信息,并发布身份验证成功的事件
if (result != null) {
//((CredentialsContainer) result).eraseCredentials();
//if (parentResult == null) {
// this.eventPublisher.publishAuthenticationSuccess(result);
//}
return result;
}
// 如果最后一个异常为空,则创建一个ProviderNotFoundException异常
if (lastException == null) {
lastException = new ProviderNotFoundException(this.messages.getMessage("ProviderManager.providerNotFound",
new Object[] { toTest.getName() }, "No AuthenticationProvider found for {0}"));
}
// 如果父验证管理器的验证异常为空,则准备抛出最后一个异常
if (parentException == null) {
prepareException(lastException, authentication);
}
// 抛出最后一个异常
throw lastException;
}
result = provider.authenticate(authentication);
其所属类public abstract class AbstractUserDetailsAuthenticationProvider implements AuthenticationProvider,
执行
// 确保传入的Authentication对象是UsernamePasswordAuthenticationToken的实例
Assert.isInstanceOf(UsernamePasswordAuthenticationToken.class, authentication,
() -> this.messages.getMessage("AbstractUserDetailsAuthenticationProvider.onlySupports",
"Only UsernamePasswordAuthenticationToken is supported"));
// 获取用户名
String username = determineUsername(authentication);
boolean cacheWasUsed = true;
// 从缓存中获取用户详细信息
UserDetails user = this.userCache.getUserFromCache(username);
if (user == null) {
cacheWasUsed = false;
try {
// 从数据源中检索用户详细信息
user = retrieveUser(username, (UsernamePasswordAuthenticationToken) authentication);
} catch (UsernameNotFoundException ex) {
this.logger.debug("Failed to find user '" + username + "'");
if (!this.hideUserNotFoundExceptions) {
throw ex;
}
// 如果用户名未找到,抛出BadCredentialsException异常
throw new BadCredentialsException(this.messages
.getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"));
}
// 确保retrieveUser方法的实现没有返回null
Assert.notNull(user, "retrieveUser returned null - a violation of the interface contract");
}
try {
// 对用户进行预身份验证检查
this.preAuthenticationChecks.check(user);
// 对用户进行额外的身份验证检查
additionalAuthenticationChecks(user, (UsernamePasswordAuthenticationToken) authentication);
} catch (AuthenticationException ex) {
if (!cacheWasUsed) {
throw ex;
}
// 如果出现问题,尝试再次进行身份验证检查,确保使用最新的数据(即不使用缓存)
cacheWasUsed = false;
user = retrieveUser(username, (UsernamePasswordAuthenticationToken) authentication);
this.preAuthenticationChecks.check(user);
additionalAuthenticationChecks(user, (UsernamePasswordAuthenticationToken) authentication);
}
// 对用户进行后身份验证检查
this.postAuthenticationChecks.check(user);
if (!cacheWasUsed) {
// 将用户详细信息放入缓存中
this.userCache.putUserInCache(user);
}
Object principalToReturn = user;
if (this.forcePrincipalAsString) {
// 如果设置了forcePrincipalAsString为true,则返回用户名作为principal
principalToReturn = user.getUsername();
}
// 创建身份验证成功的Authentication对象
return createSuccessAuthentication(principalToReturn, authentication, user);
user = retrieveUser(username, (UsernamePasswordAuthenticationToken) authentication);
其所属类class DaoAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider
执行
/**
* 从用户详细信息服务中检索用户详细信息。
*
* @param username 用户名
* @param authentication 用于身份验证的`UsernamePasswordAuthenticationToken`对象
* @return 用户详细信息
* @throws AuthenticationException 如果发生身份验证异常
*/
protected final UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication)
throws AuthenticationException {
// 准备防止时序攻击的措施
prepareTimingAttackProtection();
try {
// 通过用户详细信息服务加载指定用户名的用户详细信息
UserDetails loadedUser = this.getUserDetailsService().loadUserByUsername(username);
if (loadedUser == null) {
// 如果加载的用户详细信息为null,抛出InternalAuthenticationServiceException异常,违反了接口约定
throw new InternalAuthenticationServiceException(
"UserDetailsService returned null, which is an interface contract violation");
}
return loadedUser;
} catch (UsernameNotFoundException ex) {
// 防止时序攻击
mitigateAgainstTimingAttack(authentication);
throw ex;
} catch (InternalAuthenticationServiceException ex) {
throw ex;
} catch (Exception ex) {
// 抛出InternalAuthenticationServiceException异常,将原始异常信息作为其原因
throw new InternalAuthenticationServiceException(ex.getMessage(), ex);
}
}
UserDetails loadedUser = this.getUserDetailsService().loadUserByUsername(username);
调用自己写的loadUserByUsername();
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
@Autowired
private SysUserMapper sysUserMapper;
@Autowired
private PasswordEncoder passwordEncoder;
@Override
@Transactional
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
UserDetailsInfo userDetailsInfo = sysUserMapper.getUserInfoByUsername(username);
if(userDetailsInfo == null){
throw new UsernameNotFoundException("用戶不存在");
}
userDetailsInfo.setPassword(passwordEncoder.encode(userDetailsInfo.getPassword()));
return userDetailsInfo;
}
用户名校验
密码校验