`
sunjy22
  • 浏览: 5466 次
  • 性别: 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
分享到:
评论

相关推荐

    高版本AES-GCM模式加密的Shiro漏洞利用1

    2. Shiro框架:Shiro是一个开源的Java安全框架,提供了身份验证、授权、会话管理和加密等功能。 3. 加密算法的变化:Shiro框架在高版本中更换了加密算法,从AES-CBC换成了AES-GCM。 4. GCM参数spec:GCM参数spec是指...

    学习shiro中的加密程序

    Apache Shiro是一个强大的Java安全框架,它提供了身份验证、授权、会话管理和加密等功能,使得在Java应用中处理安全性变得更加简单。在这个“学习shiro中的加密程序”项目中,我们将会探讨Shiro如何帮助开发者实现...

    shiro实现授权登陆验证

    1. **身份验证过程**: - 用户输入用户名和密码。 - Shiro通过`Subject`接口发起身份验证请求,这通常涉及调用`Subject.login()`方法。 - SecurityManager将请求转发给配置的Realm, Realm对接口中的凭证进行匹配...

    shiro盐加密.7z

    在Shiro中,我们可以自定义 Realm 类来实现盐加密的过程,通常是在认证过程中获取用户的盐值,并与密码一起进行加密。 这个项目中可能包含以下关键组件和流程: 1. **Shiro配置**:项目可能会包含一个Spring Boot...

    Shiro_Demo 一个简单的Shiro验证框架实例

    Apache Shiro是一个强大的Java安全框架,它提供了身份验证、授权、加密和会话管理功能,使得开发者能够轻松地实现安全控制。在这个名为"Shiro_Demo"的简单示例中,我们将深入理解如何将Shiro与Spring和SpringMVC集成...

    shiro+spirngmvc 验证 IntelliJ IDEA

    Apache Shiro是一款轻量级的安全框架,适用于Java应用的安全管理,包括认证(身份验证)、授权(权限控制)、会话管理和加密服务。Shiro的简单API使得集成到现有的应用中变得容易,而不需要大量安全相关的代码。 **...

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

    SpringBoot简化了Spring应用的初始搭建以及开发过程,而Shiro则是一个强大的安全框架,提供了身份认证、授权(权限控制)、加密以及会话管理等功能。 **SpringBoot** SpringBoot的核心理念是“约定优于配置”,它...

    shiro登陆身份认证和权限管理 密码加密

    1. **身份认证**:在 Shiro 中,身份认证是验证用户是否是他们声称的那个人的过程。Shiro 提供了 `Subject` 接口作为用户与框架交互的桥梁。当用户尝试登录时,通常会调用 `Subject.login()` 方法,传递包含用户名和...

    shiro登录拦截校验demo

    Apache Shiro是一个强大的Java安全框架,它提供了身份验证(Authentication)、授权(Authorization)以及会话管理(Session Management)等功能,简化了在Java应用中处理安全问题的过程。"shiro登录拦截校验demo"是...

    Shiro入门实例

    Apache Shiro 是一个强大且易用的Java安全框架,提供了认证、授权、加密和会话管理功能,可以非常轻松地开发出足够安全的应用。在这个"Shiro入门实例"中,我们将探讨Shiro的基础知识和如何在项目中进行实战应用。 *...

    Shiro安全验证框架

    Apache Shiro是一个强大且易用的Java安全框架,它提供了身份认证、授权、加密和会话管理功能,简化了在Java应用中实现安全控制层的复杂性。本资源包括一套深度解析Shiro的开发视频、源码以及相关文档,旨在帮助...

    Shiro安全登录认证、权限授权封装模块代码

    Apache Shiro 是一个强大且易用的 Java 安全框架,它执行身份验证(Authentication)、授权(Authorization)、会话管理(Session Management)和加密(Cryptography)等核心功能。在这个项目中,你得到了一个基于 ...

    shiro身份验证、授权

    **身份验证(Authentication)**是验证用户身份的过程,即确认用户是否为他们声称的人。在Shiro中,你可以通过创建一个实现了`Subject`接口的实例来处理这个过程。通常,`Subject`代表当前用户,而`Realm`是存储用户...

    shiro认证授权的过程

    Apache Shiro 是一个强大且易用的Java安全框架,提供了认证、授权、加密和会话管理功能,可以非常方便地为应用程序提供全面的安全控制。在本文中,我们将深入理解Shiro的认证授权过程,以及如何利用它来保护我们的...

    shiro验证demo

    在"shiro验证demo"中,我们将探讨如何使用Shiro来实现用户身份验证和权限控制。 **Shiro的基本组件** 1. **认证(Authentication)**:确认用户身份的过程,即用户提供的身份凭证是否有效。在Shiro中,通常涉及...

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

    Apache Shiro是一个强大的Java安全框架,它提供了身份验证、授权、会话管理和加密等功能,使得在Java应用中处理安全性变得更加简单。在这个主题中,我们将深入探讨Shiro的核心特性,特别是与Spring框架的整合以及...

    Shiro根据用户权限显示不同的菜单.Shiro根据权限显示指定菜单

    Apache Shiro是一个强大的Java安全框架,它提供了身份验证、授权、加密和会话管理功能,为开发人员构建安全的应用程序提供便利。在这个场景中,我们关注的是如何利用Shiro实现根据用户权限动态显示不同的菜单。 ...

    shiro权限验证依赖包

    Apache Shiro是一个强大的Java安全框架,用于处理认证、授权、会话管理和加密等与安全相关的功能。在"shiro权限验证依赖包"中,包含了多个关键的库文件,这些文件协同工作以支持Shiro框架的功能。以下是每个文件的...

    Shiro 身份验证、授权、密码和会话管理

    身份验证是确认用户身份的过程。Shiro 提供了多种认证机制,如基于密码的认证、基于令牌的认证等。用户输入的凭证(通常是用户名和密码)会被传递给 Shiro,Shiro 会通过与存储在数据库或其他安全存储中的凭证进行...

    javaSE环境下Shiro认证过程以及部分API

    JavaSE环境下Apache Shiro是一个强大的安全框架,它提供了一种简单的方式来处理认证、授权、会话管理和加密等安全相关的任务。本篇文章将深入探讨Shiro的认证过程,并介绍一些常用的API,帮助你更好地理解和应用...

Global site tag (gtag.js) - Google Analytics