authentication = authenticationManager
.authenticate(new UsernamePasswordAuthenticationToken(username, password));
这个方法会调用UserDetailsServiceImpl.loadUserByUsername,此过程中调用的流程如下:
1. AuthenticationManager是个接口,ProviderManager是他的实现类。
authenticationManager.authenticate()调用其实就是ProviderManager.authenticate()
2. ProviderManager.authenticate()的代码如下:
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();
Iterator var9 = this.getProviders().iterator();
while(var9.hasNext()) {
AuthenticationProvider provider = (AuthenticationProvider)var9.next();
if (provider.supports(toTest)) {
if (logger.isTraceEnabled()) {
Log var10000 = logger;
String var10002 = provider.getClass().getSimpleName();
++currentPosition;
var10000.trace(LogMessage.format("Authenticating request with %s (%d/%d)", var10002, currentPosition, size));
}
------注意这里-------
try {
result = provider.authenticate(authentication);
if (result != null) {
this.copyDetails(authentication, result);
break;
}
} catch (InternalAuthenticationServiceException | AccountStatusException var14) {
this.prepareException(var14, authentication);
throw var14;
} catch (AuthenticationException var15) {
lastException = var15;
}
}
}
if (result == null && this.parent != null) {
try {
parentResult = this.parent.authenticate(authentication);
result = parentResult;
} catch (ProviderNotFoundException var12) {
} catch (AuthenticationException var13) {
parentException = var13;
lastException = var13;
}
}
if (result != null) {
if (this.eraseCredentialsAfterAuthentication && result instanceof CredentialsContainer) {
((CredentialsContainer)result).eraseCredentials();
}
if (parentResult == null) {
this.eventPublisher.publishAuthenticationSuccess(result);
}
return result;
} else {
if (lastException == null) {
lastException = new ProviderNotFoundException(this.messages.getMessage("ProviderManager.providerNotFound", new Object[]{toTest.getName()}, "No AuthenticationProvider found for {0}"));
}
if (parentException == null) {
this.prepareException((AuthenticationException)lastException, authentication);
}
throw lastException;
}
}
3. ProviderManager代码中找到provider.authenticate(authentication);
代码中使用 ------注意这里----- 标注了。
4. provider.authenticate(authentication)是AuthenticationProvider.authenticate(authentication)方法。
5. AuthenticationProvider也是一个接口,他的实现类是AbstractUserDetailsAuthenticationProvider。
6. AbstractUserDetailsAuthenticationProvider的子类是DaoAuthenticationProvider。
7. 在DaoAuthenticationProvider中调用了UserDetailsService
代码中使用 ------注意这里----- 标注了。
protected final UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
this.prepareTimingAttackProtection();
---------注意这里-------------
try {
UserDetails loadedUser = this.getUserDetailsService().loadUserByUsername(username);
if (loadedUser == null) {
throw new InternalAuthenticationServiceException("UserDetailsService returned null, which is an interface contract violation");
} else {
return loadedUser;
}
} catch (UsernameNotFoundException var4) {
this.mitigateAgainstTimingAttack(authentication);
throw var4;
} catch (InternalAuthenticationServiceException var5) {
throw var5;
} catch (Exception var6) {
throw new InternalAuthenticationServiceException(var6.getMessage(), var6);
}
}
8. UserDetailsService 代码如下:
public interface UserDetailsService {
UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
}
9. 写一个UserDetailsServiceImpl实现类,实现UserDetailsService ,并重写loadUserByUsername()
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException
{
SysUser user = userService.selectUserByUserName(username);
if (StringUtils.isNull(user))
{
log.info("登录用户:{} 不存在.", username);
throw new ServiceException("登录用户:" + username + " 不存在");
}
else if (UserStatus.DELETED.getCode().equals(user.getDelFlag()))
{
log.info("登录用户:{} 已被删除.", username);
throw new ServiceException("对不起,您的账号:" + username + " 已被删除");
}
else if (UserStatus.DISABLE.getCode().equals(user.getStatus()))
{
log.info("登录用户:{} 已被停用.", username);
throw new ServiceException("对不起,您的账号:" + username + " 已停用");
}
return createLoginUser(user);
}
public UserDetails createLoginUser(SysUser user)
{
return new LoginUser(user.getUserId(), user.getDeptId(), user, permissionService.getMenuPermission(user));
}
10. 到此结束 。
authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, password));就调用了UserDetailsServiceImpl.loadUserByUsername的方法。
其中的过程想要了解的建议参考AuthenticationManager 验证原理分析和AuthenticationManager 的 authentication 过程