Shiro学习笔记(三):MD5和Salt的介绍和使用

一、MD5算法的介绍

        MD5算法用于保证信息传输完整的一致。MD5是一个不可逆的字符串变换算法,它将任意长度的“字节串”变换成一个128bit的大整数。即使看到源程序和算法描述,也无法将一个MD5的值变换回原始的字符串。从数学原理上说,是因为原始的字符串有无穷多个。

        MD5的典型应用是对一段信息串产生签名,以防止被“篡改”。比方说,将一段内容写在一个文本文件中,并对这个文本文件产生一个MD5的值并进行记录,然后可以传播这个文件给别人,别人如果修改了文件中的任何内容,当我们对这个文件重新计算MD5时就会发现文件内容被修改。如果再有一个第三方的认证机构,用MD5还可以防止文件作者的“抵赖”,这就是所谓的数字签名应用。

        MD5还广泛用于加密和解密技术上,在很多操作系统中,用户的密码是以MD5值(或类似的其它算法)的方式保存的,用户Login的时候,系统是把用户输入的密码计算成MD5值,然后再去和系统中保存的MD5值进行比较,而系统并不“知道”用户的密码是什么。      

         如下图:MD5加密在service层实现,并将加密后的密码存储到数据库中。当用户登录的时候,从数据库中读取密码与用户输入的密码进行对比。

  

 二、Shiro中MD5的使用

        首先通过一个程序演示一下Md5:

package org.example.shiro;

import org.apache.shiro.crypto.hash.Md5Hash;

public class TestMD5 {
    public static void main(String[] args) {
        //MD5的使用
        Md5Hash md5Hash1 = new Md5Hash("admin");
        System.out.println(md5Hash1.toHex());
        //使用MD5+salt
        Md5Hash md5Hash2 = new Md5Hash("admin", "vasdg");
        System.out.println(md5Hash2.toHex());
        //使用MD5+Salt+hash散列
        Md5Hash md5Hash3 = new Md5Hash("admin", "vasdg", 1024);
        System.out.println(md5Hash3.toHex());
    }
}

        执行结果:

21232f297a57a5a743894a0e4a801fc3
a5599b5184c1aadc0877cd76cb93a969
578422679b493529e22c5495c8b3db3c

        md5Hash1只是Shiro中md5算法的一个简单使用, md5Hash2里加了salt处理,即任意拼接一个字符串"vasdg",默认hash次数为1,而md5Hash3是在md5Hash2的基础上hash次数为1024次。

        那么在Shiro中如何使用Md5呢?

        首先需要设置realm使用hash凭证匹配器

package org.example.shiro;

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.crypto.hash.Md5Hash;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.subject.Subject;

public class TestMD5 {
    public static void main(String[] args) {
        DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
        //注入realm
        UserMD5Realm realm = new UserMD5Realm();
        //设置realm使用hash凭证匹配器
        HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
        credentialsMatcher.setHashAlgorithmName("md5");
        realm.setCredentialsMatcher(credentialsMatcher);
        //设置Realm
        defaultSecurityManager.setRealm(realm);
        //将安装工具类中设置默认安全管理器
        SecurityUtils.setSecurityManager(defaultSecurityManager);
        //获取主体对象
        Subject subject = SecurityUtils.getSubject();
        //创建token令牌
        UsernamePasswordToken token = new UsernamePasswordToken("admin", "admin");
        try{
            //用户登录
            subject.login(token);
            System.out.println("登陆成功");
        }catch (UnknownAccountException e){
            e.printStackTrace();
            System.out.println("用户名错误");
        }catch (IncorrectCredentialsException e){
            e.printStackTrace();
            System.out.println("密码错误");
        }
    }
}

        其中,设置hash凭证匹配器代码如下:

        //设置realm使用hash凭证匹配器
        HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
        credentialsMatcher.setHashAlgorithmName("md5");
        realm.setCredentialsMatcher(credentialsMatcher);

         从上面代码可以看出:我们设置realm使用hash凭证匹配器,并指定加密算法为md5。

        其次查询数据库,对比密码即可。

package org.example.shiro;

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;

public class UserMD5Realm extends AuthorizingRealm {
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        return null;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        //获取身份信息
        String principal = (String) authenticationToken.getPrincipal();
        if("admin".equals(principal)){
            //这里的密码模拟是从数据库中读到的
            String password = "a5599b5184c1aadc0877cd76cb93a969";
            return new SimpleAuthenticationInfo(principal, password, ByteSource.Util.bytes("vasdg"), this.getName());
        }
        return null;
    }
}

        执行结果:

         以上展示了md5加密的简单过程,其hash次数为1。基于上述代码,增加散列次数:

        //设置散列次数
        credentialsMatcher.setHashIterations(1024);
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        //获取身份信息
        String principal = (String) authenticationToken.getPrincipal();
        if("admin".equals(principal)){
            //这里的密码模拟是从数据库中读到的
            String password = "578422679b493529e22c5495c8b3db3c";
            return new SimpleAuthenticationInfo(principal, password, ByteSource.Util.bytes("vasdg"), this.getName());
        }
        return null;
    }

        执行结果:

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值