`
sunjy22
  • 浏览: 5320 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

shiro验证加密过程是怎样的

阅读更多
在单步调试shiro登录源码结合张开涛的demo,学习了shiro验证加密过程是怎样的。
在核心类AuthenticatingRealm的getAuthenticationInfo(AuthenticationToken token)方法中完成登录表单提交的密码校验。
shiro类方法调用示意图


1.getAuthenticationInfo核心方法
    public final AuthenticationInfo getAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
//传入的AuthenticationToken token为表单提交参数封装的类,存储了用户名、明文密码、记住我我、主机IP。
        AuthenticationInfo info = getCachedAuthenticationInfo(token);
        if (info == null) {
//从自定义的UserRealm中获取AuthenticationInfo(一般是数据库),当作一个比较标本,用途把token生成的密文是与这个标本的密码、密文进行比较,若一致则算登录成功。
            //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;
    }

2.doGetAuthenticationInfo,自定义realm,根据token中的用户名,从数据库中获得密文、salt、realm名封装成info
@Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {

        String username = (String)token.getPrincipal();

        User user = userService.findByUsername(username);

        if(user == null) {
            throw new UnknownAccountException();//没找到帐号
        }

        if(Boolean.TRUE.equals(user.getLocked())) {
            throw new LockedAccountException(); //帐号锁定
        }

        //交给AuthenticatingRealm使用CredentialsMatcher进行密码匹配,如果觉得人家的不好可以自定义实现
        SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
                user.getUsername(), //用户名
                user.getPassword(), //密码
                ByteSource.Util.bytes(user.getCredentialsSalt()),//salt=username+salt
                getName()  //realm name
        );
        return authenticationInfo;
    }

3.assertCredentialsMatch,凭证匹配器,提交的凭证和存储的凭证进行匹配比较
//Asserts that the submitted AuthenticationToken's credentials match the stored account AuthenticationInfo's credentials
//我的理解翻译是提交的凭证和存储的凭证进行匹配比较
    protected void assertCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) throws AuthenticationException {
//返回设定的凭证匹配器(匹配规则),包含了hashAlgorithmName(加密方式名如md5)、hashIterations(加密次数)、storedCredentialsHexEncoded(密文进行16进制存储)、hashSalted(默认值false)、passwordRetryCache(密码重试缓存)5个属性。
        CredentialsMatcher cm = getCredentialsMatcher()
        if (cm != null) {
//执行密文匹配,在此时此地,token中的密码还是明文的,未加密
            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.");
        }
    }

4.doCredentialsMatch,密码错误次数后父类HashedCredentialsMatcher的doCredentialsMatch
//在自定义的RetryLimitHashedCredentialsMatcher的doCredentialsMatch方法中加入密码错误次数判断后进入父类HashedCredentialsMatcher的doCredentialsMatch。
//父类的doCredentialsMatch
    @Override
    public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
        Object tokenHashedCredentials = hashProvidedCredentials(token, info);
        Object accountCredentials = getCredentials(info);
        return equals(tokenHashedCredentials, accountCredentials);
    }

5.hashProvidedCredentials,从info中取出salt,和表单提交的密码一个需认证的Hash
//取出盐
protected Object hashProvidedCredentials(AuthenticationToken token, AuthenticationInfo info) {
        Object salt = null;
        if (info instanceof SaltedAuthenticationInfo) {
            salt = ((SaltedAuthenticationInfo) info).getCredentialsSalt();
        } else {
            //retain 1.0 backwards compatibility:
            if (isHashSalted()) {
                salt = getSalt(token);
            }
        }
        return hashProvidedCredentials(token.getCredentials(), salt, getHashIterations());
    }
//生成hash
//Object credentials 用户名
//Object salt 盐
//int hashIterations hash次数
    protected Hash hashProvidedCredentials(Object credentials, Object salt, int hashIterations) {
//算法名,如md5
        String hashAlgorithmName = assertHashAlgorithmName();
//创建用户账号时生成的密文也是生成一个SimpleHash,构造参数多一个hashIterations
        return new SimpleHash(hashAlgorithmName, credentials, salt, hashIterations);
    }

6.getCredentials,从存储的info中提取密文,转换成一个hash对象
//    protected Object getCredentials(AuthenticationInfo info) {
        Object credentials = info.getCredentials();

        byte[] storedBytes = toBytes(credentials);

        if (credentials instanceof String || credentials instanceof char[]) {
            //account.credentials were a char[] or String, so
            //we need to do text decoding first:
            if (isStoredCredentialsHexEncoded()) {
                storedBytes = Hex.decode(storedBytes);
            } else {
                storedBytes = Base64.decode(storedBytes);
            }
        }
        AbstractHash hash = newHashInstance();
        hash.setBytes(storedBytes);
        return hash;
    }
//两个hash对象进行比较

7.equals,两个hash对象进行比较
    protected boolean equals(Object tokenCredentials, Object accountCredentials) {
        if (log.isDebugEnabled()) {
            log.debug("Performing credentials equality check for tokenCredentials of type [" +
                    tokenCredentials.getClass().getName() + " and accountCredentials of type [" +
                    accountCredentials.getClass().getName() + "]");
        }
        if (isByteSource(tokenCredentials) && isByteSource(accountCredentials)) {
            if (log.isDebugEnabled()) {
                log.debug("Both credentials arguments can be easily converted to byte arrays.  Performing " +
                        "array equals comparison");
            }
//最终都转换成字节数组进行比较
            byte[] tokenBytes = toBytes(tokenCredentials);
            byte[] accountBytes = toBytes(accountCredentials);
            return Arrays.equals(tokenBytes, accountBytes);
        } else {
            return accountCredentials.equals(tokenCredentials);
        }
    }
  • 大小: 31 KB
分享到:
评论

相关推荐

    SpringBoot + shiro Demo 简单登录验证权限验证

    SpringBoot ,Shiro 密码加密,登录验证,权限控制demo

    尚硅谷Shiro视频教程

    尚硅谷_Shiro_多 Realm 验证 · 14.尚硅谷_Shiro_认证策略 · 15.尚硅谷_Shiro_把 realms 配置给 SecurityManager · 16. 尚硅谷_Shiro_权限配置 · 17.尚硅谷_Shiro_授权流程分析 · 18.尚硅谷_Shiro_多 Realm...

    Shiro框架三部曲

    Shiro是Apache从JSecret项目演变而来的,该框架实现了:用户登录、认证、授权和权限管理操作的完整控制流程。Shiro最早的名字是JSecurity,后来...用于简洁地处理身份验证,授权,企业多个系统会话管理,加密服务等。

    关于Shiro的相关,包括登录权限等,加密加盐,与Spring整合,从Redis缓存中获取数据

    关于Shiro的相关,包括登录权限等,加密加盐,与Spring整合,从Redis缓存中获取数据

    shiro安全框架整合Mybatis

    Apache Shiro是一个功能强大且易于使用的Java安全框架,可执行身份验证、授权、加密和会话管理。目前,使用 Apache Shiro 的人越来越多,因为它相当简单,对比 Spring Security,可能没有 Spring Security 做的功能...

    springboot+shiro+md5

    这里详细记录一次springboot使用shiro进行登录验证操作,同时结合MD5加密技术,实现web后台的登录功能。

    单点登录sso-shiro-cas-maven

    其中shiro.loginUrl 跟 shiro.logoutUrl的前面是cas验证的地址,后面的是我们应用系统的地址,这样配置的方式是为了在访问我们的应用系统的时候,先到cas进行验证,如果验证成功了,cas将重定向到shiro.successUrl ...

    Apache_Shiro参考手册中文版.zip

    Apache Shiro 是一个强大而灵活的开源安全框架,它干净利落地处理身份认证,授权,企业会话管理和加密。 Apache Shiro 的首要目标是易于使用和理解。安全有时候是很复杂的,甚至是痛苦的,但它没有必要这样。框架应 ...

    SpringBoot + Apache Shiro1.9.1 最新版本详细教程,基于RBAC角色访问、安全管理框架、用户角色权限

    4、优点:快速上手、全面支持验证、授权、加密和会话、灵活自定义设计、支持web环境、可以无缝集成spring等优点。可以用来用户验证、用户授权、用户session管理、安全加密等 5、基于RBAC五张表:用户表 tb_user、...

    简单的介绍,简单的配置,简单的扩展 shiro入门学习手册 共35页.pptx

    Apache Shiro是一个强大而灵活的开源安全框架,它能够干净利落地处理身份认证,授权,企业会话管理和加密。 以下是你可以用 Apache Shiro所做的事情: ? 验证用户 ? 对用户执行访问控制,如: ? 判断用户是否...

    Apache Shiro中文开发文档.pdf

    Apache Shiro 是一个强大而灵活的开源安全框架,它干净利落地处理身份认证,授权,企业会话管理和加密。 Apache Shiro 的首要目标是易于使用和理解。安全有时候是很复杂的,甚至是痛苦的,但它没有必要这样。框架...

    最详细Shiro学习资料(源码)

    Shiro(Apache Shiro)是一个强大且易于使用的Java安全框架,用于身份验证、授权、加密和会话管理等安全功能。它提供了简单的API和灵活的配置选项,可以方便地集成到现有的Java应用程序中。 Shiro的主要特点包括: ...

    shiro-all-1.2.1.jar

    shiro是apache提供的强大而灵活的开源安全框架,它主要用来处理身份认证,授权,企业会话管理和加密。 shiro功能:用户验证、用户执行访问权限控制、在任何环境下使用session API,如cs程序。

    Spring Boot 整合 Shiro.docx

    它可以干净利落地处理身份验证、授权、企业会话管理和加密。 Apache Shiro 的首要目标是易于使用和理解。安全通常很复杂,甚至让人感到很痛苦,但是 Shiro 却不是这样子的。一个好的安全框架应该屏蔽复杂性,向外...

    shiro-web-1.3.2.jar包

    Apache Shiro是Java的一个安全框架,旨在简化身份验证和授权。Shiro在JavaSE和JavaEE项目中都可以使用。它主要用来处理身份认证,授权,企业会话管理和加密等。

    shiro框架教程

    Apache Shiro是Java的一个安全框架,旨在简化身份验证和授权。Shiro在JavaSE和JavaEE项目中都可以使用。它主要用来处理身份认证,授权,企业会话管理和加密等

    shiro教程文档-张开涛

    shiro文档张开涛,文档详细,层次分明。Shiro 简介、身份验证、授权、INI 配置、编码/加密、Realm 及相关对象、与 Web 集成.....

    shiro-web-master.zip

    学习shiro的课程,包含了加密,登陆,验证,redis缓存等信息

    Java-Shiro学习思维导图.zip

    Java Shiro 是一个强大且灵活的开源安全框架,用于身份认证、授权和会话管理等安全领域...学习如何使用 Shiro 进行密码的加密和验证。 了解不同的密码加密算法和安全性。 Remember Me 功能: 理解 Remember Me 功能的

    shiro入门学习.ppt

    Apache Shiro是一个强大而灵活的开源安全框架,它能够干净利落地处理身份认证,授权,企业会话管理和加密。 以下是你可以用 Apache Shiro所做的事情:  验证用户  对用户执行访问控制,如:  判断用户...

Global site tag (gtag.js) - Google Analytics