springSecurity登录验证分析——AbstractUserDetailsAuthenticationProvider
2014-05-07 17:38
429 查看
AbstractUserDetailsAuthenticationProvider类位于org.springframework.security.authentication.dao包下,在
org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter中被调用,
该类的public Authentication authenticate(Authentication authentication) throws AuthenticationException方法百常重要,通过这段代码能详细了解整个验证的过程,下面对该方法的代码分段进行说明:
(1) Assert.isInstanceOf(UsernamePasswordAuthenticationToken.class, authentication,
messages.getMessage("AbstractUserDetailsAuthenticationProvider.onlySupports",
"Only UsernamePasswordAuthenticationToken is supported"));
//要求传入的authentication对象必须是UsernamePasswordAuthenticationToken类或其子类的实例
(2)
String username = (authentication.getPrincipal() == null) ? "NONE_PROVIDED" : authentication.getName();
//从authentication中取出登录名
(3) boolean cacheWasUsed = true;
UserDetails user = this.userCache.getUserFromCache(username);
//默认情况下从缓存中(UserCache接口实现)取出用户信息
(4)
if (user == null) {
//如果从内存中取不到用户,则设置cacheWasUsed 为false,供后面使用
cacheWasUsed = false;
try {
//retrieveUser是抽象方法,通过子类来实现获取用户的信息,以UserDetails接口形式返回
user = retrieveUser(username, (UsernamePasswordAuthenticationToken) authentication);
} catch (UsernameNotFoundException notFound) {
logger.debug("User '" + username + "' not found");
if (hideUserNotFoundExceptions) {
throw new BadCredentialsException(messages.getMessage(
"AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"));
} else {
throw notFound;
}
}
Assert.notNull(user, "retrieveUser returned null - a violation of the interface contract");
}
(5)
try {
//preAuthenticationChecks和additionalAuthenticationChecks这是UserDetailsChecker接口的实现类
//验证帐号是否锁定\是否禁用\帐号是否到期
preAuthenticationChecks.check(user);
//由子类来完成更进一步的验证
additionalAuthenticationChecks(user, (UsernamePasswordAuthenticationToken) authentication);
} catch (AuthenticationException exception) {
//下面这段代码体现了老外的细腻之处,意思是说如果在调用某个UserDetailsChecker接口的实现类验证失败后,就判断下用户信息是否从内存中得到,如果之前是从内存中得到的用户信息,那么考虑到可能数据是不实时的,就重新通过retrieveUser方法去取出用户信息,再次重复进行检查验证
if (cacheWasUsed) {
// There was a problem, so try again after checking
// we're using latest data (i.e. not from the cache)
cacheWasUsed = false;
user = retrieveUser(username, (UsernamePasswordAuthenticationToken) authentication);
preAuthenticationChecks.check(user);
additionalAuthenticationChecks(user, (UsernamePasswordAuthenticationToken) authentication);
} else {
throw exception;
}
}
(6) //在spring的框架设计中经常能看到这样的前置处理和后置处理,此处后置处理只是判断了下用户的密码是否过期,如过期则记入日志
postAuthenticationChecks.check(user);
//如果没有缓存则进行缓存,则处的userCache是由NullUserCache类实现的,名如其义,该类的putUserInCache没做任何事
if (!cacheWasUsed) {
this.userCache.putUserInCache(user);
}
(7)
//以下代码主要是把用户的信息和之前用户提交的认证信息重新组合成一个authentication实例返回,返回类是
UsernamePasswordAuthenticationToken类的实例
Object principalToReturn = user;
if (forcePrincipalAsString) {
principalToReturn = user.getUsername();
}
return createSuccessAuthentication(principalToReturn, authentication, user);
-----------------------------------------------------------------------------------
代码分析到此,另外再附上类图方便理解。
org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter中被调用,
该类的public Authentication authenticate(Authentication authentication) throws AuthenticationException方法百常重要,通过这段代码能详细了解整个验证的过程,下面对该方法的代码分段进行说明:
(1) Assert.isInstanceOf(UsernamePasswordAuthenticationToken.class, authentication,
messages.getMessage("AbstractUserDetailsAuthenticationProvider.onlySupports",
"Only UsernamePasswordAuthenticationToken is supported"));
//要求传入的authentication对象必须是UsernamePasswordAuthenticationToken类或其子类的实例
(2)
String username = (authentication.getPrincipal() == null) ? "NONE_PROVIDED" : authentication.getName();
//从authentication中取出登录名
(3) boolean cacheWasUsed = true;
UserDetails user = this.userCache.getUserFromCache(username);
//默认情况下从缓存中(UserCache接口实现)取出用户信息
(4)
if (user == null) {
//如果从内存中取不到用户,则设置cacheWasUsed 为false,供后面使用
cacheWasUsed = false;
try {
//retrieveUser是抽象方法,通过子类来实现获取用户的信息,以UserDetails接口形式返回
user = retrieveUser(username, (UsernamePasswordAuthenticationToken) authentication);
} catch (UsernameNotFoundException notFound) {
logger.debug("User '" + username + "' not found");
if (hideUserNotFoundExceptions) {
throw new BadCredentialsException(messages.getMessage(
"AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"));
} else {
throw notFound;
}
}
Assert.notNull(user, "retrieveUser returned null - a violation of the interface contract");
}
(5)
try {
//preAuthenticationChecks和additionalAuthenticationChecks这是UserDetailsChecker接口的实现类
//验证帐号是否锁定\是否禁用\帐号是否到期
preAuthenticationChecks.check(user);
//由子类来完成更进一步的验证
additionalAuthenticationChecks(user, (UsernamePasswordAuthenticationToken) authentication);
} catch (AuthenticationException exception) {
//下面这段代码体现了老外的细腻之处,意思是说如果在调用某个UserDetailsChecker接口的实现类验证失败后,就判断下用户信息是否从内存中得到,如果之前是从内存中得到的用户信息,那么考虑到可能数据是不实时的,就重新通过retrieveUser方法去取出用户信息,再次重复进行检查验证
if (cacheWasUsed) {
// There was a problem, so try again after checking
// we're using latest data (i.e. not from the cache)
cacheWasUsed = false;
user = retrieveUser(username, (UsernamePasswordAuthenticationToken) authentication);
preAuthenticationChecks.check(user);
additionalAuthenticationChecks(user, (UsernamePasswordAuthenticationToken) authentication);
} else {
throw exception;
}
}
(6) //在spring的框架设计中经常能看到这样的前置处理和后置处理,此处后置处理只是判断了下用户的密码是否过期,如过期则记入日志
postAuthenticationChecks.check(user);
//如果没有缓存则进行缓存,则处的userCache是由NullUserCache类实现的,名如其义,该类的putUserInCache没做任何事
if (!cacheWasUsed) {
this.userCache.putUserInCache(user);
}
(7)
//以下代码主要是把用户的信息和之前用户提交的认证信息重新组合成一个authentication实例返回,返回类是
UsernamePasswordAuthenticationToken类的实例
Object principalToReturn = user;
if (forcePrincipalAsString) {
principalToReturn = user.getUsername();
}
return createSuccessAuthentication(principalToReturn, authentication, user);
-----------------------------------------------------------------------------------
代码分析到此,另外再附上类图方便理解。
相关文章推荐
- springSecurity登录验证分析——AbstractUserDetailsAuthenticationProvider
- springSecurity登录验证分析——AbstractUserDetailsAuthenticationProvider
- exception: AbstractUserDetailsAuthenticationProvider.badCredentials
- exception: AbstractUserDetailsAuthenticationProvider.badCredentials
- 用户登录:Spring Security3源码分析-UsernamePasswordAuthenticationFilter分析
- Spring Security 的登录密码验证过程 UsernamePasswordAuthenticationFilter
- Spring Security 入门(3-11)Spring Security 的登录密码验证过程 UsernamePasswordAuthenticationFilter
- mysql登录用户验证遇到的问题 access denied for user ‘user’@'localhost'
- springSecurity的登录验证
- UsernamePasswordAuthenticationFilter是登陆用户密码验证过滤器,
- “User Profile Service未能登录“问题分析对策总汇
- 腾讯QQ空间登录的方法实现方式与验证过程分析
- UserNamePasswrodAuthenticationFilter验证过程
- openfire登录验证AuthProvider
- Weblogic验证提供程序控制标记(Authentication provider Control Flag)详解
- springSecurity的登录验证
- ASP.NET(c#) 中通过配置配置authentication 来验证控制 Login 登录
- Spring Security3源码分析(7)-UsernamePasswordAuthenticationFilter分析
- SecureCRT通过SSH服务登录ubuntu出错:Password authentication failed, Please verify that the username and passw
- springSecurity的登录验证