MD5算法

    1. 作用:一般用来加密 或者 签名
    2. 特点:MD5算法不可逆 如果内容相同无论执行多少次md5生成结果始终一致
    3. 生成结果:始终是一个16进制32位长度的字符串

    image.png

    package com.cedric;
    
    import org.apache.shiro.crypto.hash.Md5Hash;
    
    public class TestShiroMD5 {
        public static void main(String[] args) {
    
    
            //创建一个MD5算法
           /* Md5Hash md5Hash = new Md5Hash();
            md5Hash.setBytes("123".getBytes());
            String s = md5Hash.toHex();
            System.out.println(s);*/
    
            //使用MD5
            Md5Hash md5Hash = new Md5Hash("123");
    
            System.out.println(md5Hash.toHex());
    
            // 使用MD5 + salt 处理
            Md5Hash md5Hash1 = new Md5Hash("123","0X*P");
            System.out.println(md5Hash1.toHex());
    
            //使用MD5 + salt + hash散列
            Md5Hash md5Hash2 = new Md5Hash("123","0X*P",1024);
            System.out.println(md5Hash2.toHex());
        }
    }
    

    使用MD5和Salt

    实际应用是将盐和散列后的值存在数据库中,自动realm从数据库取出盐和加密后的值由shiro完成密码校验
    

    自定义MD5 + salt的realm

    package com.cedric.realm;
    
    import org.apache.shiro.authc.AuthenticationException;
    import org.apache.shiro.authc.AuthenticationInfo;
    import org.apache.shiro.authc.AuthenticationToken;
    import org.apache.shiro.authc.SimpleAuthenticationInfo;
    import org.apache.shiro.authz.AuthorizationInfo;
    import org.apache.shiro.realm.AuthorizingRealm;
    import org.apache.shiro.subject.PrincipalCollection;
    import org.apache.shiro.util.ByteSource;
    
    /**
     *
     * 使用自定义realm 加上 MD5 + salt + hash
     */
    public class CustomerMd5Realm extends AuthorizingRealm {
        @Override
        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
            return null;
        }
    
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
            //获取身份信息
            String principal = (String) authenticationToken.getPrincipal();
    
            //根据用户名查询数据库
            if ("Jack".equals(principal)){
    
                //参数1:数据库用户名  参数2:数据库md5+salt之后的密码  参数3:注册时的随机盐  参数4:realm的名字
                return new SimpleAuthenticationInfo(principal,
                        "0c3fd70bf5939dccaad22d27bfa46298",
                        ByteSource.Util.bytes("0X*P"),
                        this.getName());
            }
            return null;
        }
    }
    
    package com.cedric;
    
    import com.cedric.realm.CustomerMd5Realm;
    import org.apache.shiro.SecurityUtils;
    import org.apache.shiro.authc.IncorrectCredentialsException;
    import org.apache.shiro.authc.UnknownAccountException;
    import org.apache.shiro.authc.UsernamePasswordToken;
    import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
    import org.apache.shiro.mgt.DefaultSecurityManager;
    import org.apache.shiro.subject.Subject;
    
    public class TestCustomerMd5RealmAuthenicator {
    
        public static void main(String[] args) {
    
            //创建安全管理器
            DefaultSecurityManager securityManager = new DefaultSecurityManager();
            //注入Realm
            CustomerMd5Realm realm = new CustomerMd5Realm();
            //设置realm使用hash凭证匹配器
    
            HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
            //使用算法
            credentialsMatcher.setHashAlgorithmName("md5");
            //散列次数
            credentialsMatcher.setHashIterations(1024);
            realm.setCredentialsMatcher(credentialsMatcher);
    
            securityManager.setRealm(realm);
            //将安全工具类注入安全工具
            SecurityUtils.setSecurityManager(securityManager);
            //通过安全工具获取subject
            Subject subject = SecurityUtils.getSubject();
            //认证
            UsernamePasswordToken token = new UsernamePasswordToken("Jack","123");
    
            try {
                subject.login(token);
                System.out.println("登录成功");
            } catch (UnknownAccountException e){
                e.printStackTrace();
                System.out.println("用户名错误");
            } catch (IncorrectCredentialsException e){
                e.printStackTrace();
                System.out.println("密码错误");
            }
    
        }
    }