简单记录一下shiro的验证流程

来源:互联网 发布:搞笑诺贝尔奖 知乎 编辑:程序博客网 时间:2024/05/21 05:43

关于shiro我就不说了,公司的用到shiro这两天看了下,又重新认知了一遍用户角色权限之间的关系,在看shiro和web集成的时候,关于验证流程这一块记录一下。
这里直接写验证流程了:关于配置就不说了,这是与数据库交互的shiro要依赖service层,嗯 先看是怎么验证的
了解shiro之后呢,我们都是自己去实现一个realm重写认证和权限函数(这里只说登录)。代码如下:

public class ShiroDbRealm extends AuthorizingRealm {    protected AccountService accountService;    /**     * 认证回调函数,登录时调用.     */    @Override    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException {        UsernamePasswordToken token = (UsernamePasswordToken) authcToken;        User user = accountService.findUserByLoginName(token.getUsername());        if (user != null) {            byte[] salt = Encodes.decodeHex(user.getSalt());                  return new SimpleAuthenticationInfo(new ShiroUser(user.getId(), user.getLoginName(), user.getName()),                    user.getPassword(), ByteSource.Util.bytes(salt), getName());        } else {                  return null;        }    }    /**     * 授权查询回调函数, 进行鉴权但缓存中无用户的授权信息时调用.     */    @Override    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {        ShiroUser shiroUser = (ShiroUser) principals.getPrimaryPrincipal();        User user = accountService.findUserByLoginName(shiroUser.loginName);        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();        info.addRoles(user.getRoleList());        return info;    }    /**     * 设定Password校验的Hash算法与迭代次数.     */    @PostConstruct    public void initCredentialsMatcher() {        HashedCredentialsMatcher matcher = new HashedCredentialsMatcher(AccountService.HASH_ALGORITHM);        matcher.setHashIterations(AccountService.HASH_INTERATIONS);        setCredentialsMatcher(matcher);//这里把匹配器传过去    }    public void setAccountService(AccountService accountService) {        this.accountService = accountService;    }    /**     * 自定义Authentication对象,使得Subject除了携带用户的登录名外还可以携带更多信息.     */    public static class ShiroUser implements Serializable {        private static final long serialVersionUID = -1373760761780840081L;        public Long id;        public String loginName;        public String name;        public ShiroUser(Long id, String loginName, String name) {            this.id = id;            this.loginName = loginName;            this.name = name;        }        public String getName() {            return name;        }        /**         * 本函数输出将作为默认的<shiro:principal/>输出.         */        @Override        public String toString() {            return loginName;        }        /**         * 重载hashCode,只计算loginName;         */        @Override        public int hashCode() {            return Objects.hashCode(loginName);        }        /**         * 重载equals,只计算loginName;         */        @Override        public boolean equals(Object obj) {            if (this == obj) {                return true;            }            if (obj == null) {                return false;            }            if (getClass() != obj.getClass()) {                return false;            }            ShiroUser other = (ShiroUser) obj;            if (loginName == null) {                if (other.loginName != null) {                    return false;                }            } else if (!loginName.equals(other.loginName)) {                return false;            }            return true;        }    }}

但看这里可能会很迷茫,密码验证呢?

setCredentialsMatcher(matcher);//这里把匹配器传过去
在这里看到传了一个matcher于是我们继续打开这个方法的源码如下:

public abstract class AuthenticatingRealm extends CachingRealm implements Initializable {................ public void setCredentialsMatcher(CredentialsMatcher credentialsMatcher) {        this.credentialsMatcher = credentialsMatcher;    }    ...........protected void assertCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) throws AuthenticationException {        CredentialsMatcher cm = getCredentialsMatcher();        if (cm != null) {            if (!cm.doCredentialsMatch(token, info)) {                //not successful - throw an exception to indicate this:                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.");        }

是这个抽象类AuthenticatingRealm的方法,再往下看getCredentialsMatcher();就看到了Info和token那么就是数据的比较了
cm.doCredentialsMatch(token, info)
再往下看无非就是一些解密比较返回了

内部流程:
1.AuthenticatingRealm继承CachingRealm执行getAuthenticationInfo

2.调用SimpleCredentialsMatcher的doCredentialsMatch()

原创粉丝点击