Shiro|AuthenticatingRealm的认证流程(简要)

AuthenticatingRealm的认证流程(简要)

推荐资源

从login()到Realm的doGetAuthenticationInfo之间发生了什么?

Shiro 身份验证

Realm类图

在这里插入图片描述

getAuthenticationInfo方法

AuthenticatingRealm的getAuthenticationInfo方法有两点功能:

  1. 通过缓存或者Realm的doGetAuthenticationInfo方法来获取AuthenticationInfo
  2. 校验AuthenticationToken与AuthenticationInfo的Credentials是否一致
    public final AuthenticationInfo getAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        AuthenticationInfo info = this.getCachedAuthenticationInfo(token);
        if (info == null) {
            info = this.doGetAuthenticationInfo(token);
            log.debug("Looked up AuthenticationInfo [{}] from doGetAuthenticationInfo", info);
            if (token != null && info != null) {
                this.cacheAuthenticationInfoIfPossible(token, info);
            }
        } else {
            log.debug("Using cached authentication info [{}] to perform credentials matching.", info);
        }

        if (info != null) {
        	// 校验AuthenticationToken与AuthenticationInfo的Credentials是否一致
            this.assertCredentialsMatch(token, info);
        } else {
            log.debug("No AuthenticationInfo found for submitted AuthenticationToken [{}].  Returning null.", token);
        }

        return info;
    }

assertCredentialsMatch方法

assertCredentialsMatch方法在getAuthenticationInfo方法中被调用,用以校验AuthenticationToken与AuthenticationInfo的Credentials是否一致。

如果校验失败,则抛出相应的异常,意味着整个认证过程失败。

protected void assertCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) throws AuthenticationException {
        CredentialsMatcher cm = this.getCredentialsMatcher();
        if (cm != null) {
            if (!cm.doCredentialsMatch(token, info)) {
                String msg = "Submitted credentials for token [" + token + "] did not match the expected credentials.";
                throw new IncorrectCredentialsException(msg);
            }
        } else {
            throw new AuthenticationException("A CredentialsMatcher must be configured in order to verify credentials during authentication.  If you do not wish for credentials to be examined, you can configure an " + AllowAllCredentialsMatcher.class.getName() + " instance.");
        }
    }

注意:Realm的CredentialsMatcher是可以自定义的。

自定义CredentialsMatcher

如需要自定义CredentialsMatcher,只需要实现CredentialsMatcher接口,在doCredentialsMatch方法中校验info与token的Credentials是否一致即可。

import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.credential.CredentialsMatcher;

public class MyCredentialsMatcher implements CredentialsMatcher {
    @Override
    public boolean doCredentialsMatch(AuthenticationToken authenticationToken, AuthenticationInfo authenticationInfo) {
        String password = (String)authenticationInfo.getCredentials();
        String arg = new String((char[])authenticationToken.getCredentials());
        return password.equals(arg);
    }
}

附:配置shrio配置文件

myMatcher=matcher.MyCredentialsMatcher
myRealm=realm.MyRealm
myRealm.credentialsMatcher=$myMatcher
securityManager.realms=$myRealm

认证过程简单示例

在本例中(单Realm且R自定义Realm继承自AuthorizingRealm),执行Subject.login()后,Shiro会层层调用至AuthenticatingRealm的getAuthenticationInfo并在其中调用自定义Realm的doGetAuthenticationInfo方法。

在自定义Realm类的doGetAuthenticationInfo方法中,我们在数据库中查询了用户的账户与密码,构造了SimpleAuthenticationInfo对象并返回。

然后,自定义Realm类的父类AuthenticatingRealm会执行assertCredentialsMatch方法进行Credentials的校验。

package realm;

import entity.User;
import org.apache.shiro.authc.*;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import service.UserService;
import service.UserServiceImpl;

public class MyRealm extends AuthorizingRealm {

    private UserService userService = new UserServiceImpl();

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        return null;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        // 获得输入的用户名及密码
        String username = (String) authenticationToken.getPrincipal();
        String password = new String((char[])authenticationToken.getCredentials());
        // 从数据库中查询用户
        User user = userService.findByUsername(username);
        if(user == null)
            throw new UnknownAccountException("不存在的用户名!");
        // 返回认证信息
        return new SimpleAuthenticationInfo(user.getUsername(),user.getPassword(),getName());
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值