shiro密码验证的大致流程:

1. controller中login的时候

        UsernamePasswordToken token = new UsernamePasswordToken(account, password);
        try {
            SecurityUtils.getSubject().login(token);
        }

2. realm中调用doGetAuthenticationInfo

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authToken) throws AuthenticationException {
        String username = (String)authToken.getPrincipal();
        User user = userService.getUserByAccount(username);
        if (user == null) {
            throw new UnknownAccountException();
        }

        //交给AuthenticatingRealm使用CredentialsMatcher进行密码匹配,如果觉得人家的不好可以自定义实现
        /**
         * 这里传入的user信息,只是从数据库中查询到的结果,
         * shiro会将token中的明文,按照配置中的加密方式进行加密,然后进行匹配。
         * 有些教程,在这里将明文的pwd加密后传入,是没有必要的
         */
        SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
                user.getAccount(),
                user.getPassword(),
//                ByteSource.Util.bytes(user.getAccount() + user.getSalt()),
                ByteSource.Util.bytes(user.getSalt()),
                getName()
        );

        /**
         * 写入session,但是移除password信息
         */
        user.setPassword("");
        user.setSalt("");
        SecurityUtils.getSubject().getSession().setAttribute(SessionConstant.SESS_USER_INFO, user);
        return authenticationInfo;
    }

需要注意的是,很多人认为需要在这里传入加密后的密码,进行匹配,这是个误解。

如果出现报错Submitted credentials for token [org.apache.shiro.authc.UsernamePasswordToken,出现这种情况是因为密码验证不通过,原因有:

1. 没有设置加密算法,却进行加密匹配

2. 密码虽然加密,但是加密算法、迭代次数与配置文件中不一致

public HashedCredentialsMatcher credentialsMatcher() {
        HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
        credentialsMatcher.setHashAlgorithmName("md5");
        credentialsMatcher.setHashIterations(2);
        // true 密码加密用hex编码; false 用base64编码
        credentialsMatcher.setStoredCredentialsHexEncoded(true);
        return credentialsMatcher;
    }

3. 排除1和2后,很可能就是配置文件有问题了

针对情况3,我遇到过的情况如下:

忘记设置customerRealm.setCredentialsMatcher(credentialsMatcher())导致密码匹配出错

@Bean
    public CustomerRealm customerRealm() {
        CustomerRealm customerRealm = new CustomerRealm();
        /**
         * 密文匹配的时候,这里需要设置credentialsMatcher(),否则无法匹配
         */
        customerRealm.setCredentialsMatcher(credentialsMatcher());
        return customerRealm;
    }

 

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐