Shiro:HashedCredentialsMatcher 未被使用的原因

293 阅读2分钟

我自定义的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;

    }