Shiro:HashedCredentialsMatcher 未
我自定义的UserRealm 继承自AuthorizingRealm,AuthorizingRealm 又继承了AuthenticatingRealm,而AuthenticatingRealm 又继承了
CachingRealm。
再用subject.login()方法登录时,subject调用securityManager的login方法,如果用的是其默认实现类DefaultSecurityManager,
在DefaultSecurityManager的login方法中调用authenticate方法进行认证,authenticate方法是其DefaultSecurityManager父类
AuthenticatingSecurityManager的方法,AuthenticatingSecurityManager 中组合了接口 authenticator:Authenticator,
然后调用authenticator.authenticate(token), Authenticator 的抽象实现 AbstractAuthenticator 调用 doAuthenticate(token)方法,
这个方法又会去调用shiro提供的AbstractAuthenticator的子类 ModularRealmAuthenticator 的 doAuthenticate(token) 方法。
它回去判断有几个Reaml被注册到shiro中,我这里只有一个,所以不会涉及到验证策略。然后它调用
doSingleRealmAuthentication(realms.iterator().next(), authenticationToken)方法,
doSingleRealmAuthentication 方法中又会去调用 realm.getAuthenticationInfo(token);
一开始说了,咱们的UserRealm 间接继承了AuthenticatingRealm,所以下面就是AuthenticatingRealm中的getAuthenticationInfo方法。
他一开始就去调缓存中的信息,因为第一次调cache,肯定为 null,第二次才缓存。所以 他回去调 我自定义的UserReaml中的 doGetAuthenticationInfo 方法,但是我在这里面做了密码判断,密码错误就直接抛出异常,所以不可能执行CredentialsMatcher,这就是为啥CredentialsMatcher没有被使用的原因。说明,我对Reaml的理解还不够,realm千万不能做密码正确性判断,但可以做其他判断并抛出异常。
/**
* This implementation functions as follows:
* <ol>
* <li>It attempts to acquire any cached {@link AuthenticationInfo} corresponding to the specified
* {@link AuthenticationToken} argument. If a cached value is found, it will be used for credentials matching,
* alleviating the need to perform any lookups with a data source.</li>
* <li>If there is no cached {@link AuthenticationInfo} found, delegate to the
* {@link #doGetAuthenticationInfo(org.apache.shiro.authc.AuthenticationToken)} method to perform the actual
* lookup. If authentication caching is enabled and possible, any returned info object will be
* {@link #cacheAuthenticationInfoIfPossible(org.apache.shiro.authc.AuthenticationToken, org.apache.shiro.authc.AuthenticationInfo) cached}
* to be used in future authentication attempts.</li>
* <li>If an AuthenticationInfo instance is not found in the cache or by lookup, {@code null} is returned to
* indicate an account cannot be found.</li>
* <li>If an AuthenticationInfo instance is found (either cached or via lookup), ensure the submitted
* AuthenticationToken's credentials match the expected {@code AuthenticationInfo}'s credentials using the
* {@link #getCredentialsMatcher() credentialsMatcher}. This means that credentials are always verified
* for an authentication attempt.</li>
* </ol>
*
* @param token the submitted account principal and credentials.
* @return the AuthenticationInfo corresponding to the given {@code token}, or {@code null} if no
* AuthenticationInfo could be found.
* @throws AuthenticationException if authentication failed.
*/
public final AuthenticationInfo getAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
AuthenticationInfo info = getCachedAuthenticationInfo(token);
if (info == null) {
//otherwise not cached, perform the lookup:
info = doGetAuthenticationInfo(token);
log.debug("Looked up AuthenticationInfo [{}] from doGetAuthenticationInfo", info);
if (token != null && info != null) {
cacheAuthenticationInfoIfPossible(token, info);
}
} else {
log.debug("Using cached authentication info [{}] to perform credentials matching.", info);
}
if (info != null) {
assertCredentialsMatch(token, info);
} else {
log.debug("No AuthenticationInfo found for submitted AuthenticationToken [{}]. Returning null.", token);
}
return info;
}
UserRealm 中的doGetAuthenticationInfo方法
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
String email = token.getPrincipal().toString();
User userDB = userService.findByEmail(email);
if (userDB == null) {
throw new UnknownAccountException("邮箱找不到");
}
if (userDB.getStatus() == ReturnValue.ACCOUNT_NOT_ACTIVATED.getCode()){
throw new DisabledAccountException("用户未激活");
}
if (!userDB.equals(token.getCredentials().toString())){
throw new IncorrectCredentialsException("密码错误");
}
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(userDB.getEmail(),userDB.getPassword(), getName());
// if (userDB.getSalt() != null) {
// info.setCredentialsSalt(ByteSource.Util.bytes(userDB.getSalt()));
// }
return info;
}