springboot集成shiro(二)

shiro加密介绍

上一节我们讲了springboot基础shiro的基本原理,没有对密码进行加密处理,显然这样是不行的。这节我们来讲shiro是如何对密码进行加密处理的。
原理很简单,1就是创建用户的时候用shiro加密算法对密码进行加密,2登录的时候用同样的方法进行解密,加密解密一定要一一对应。
shiro自带加密算法如下:

  • Md5
  • Base64
  • Sha1,Sha256,Sha512
  • SimleHash
  • Hex

使用参考示例如下:

/**
 * @Description TODO
 * @Author www.moyundong.com
 * @Date 2020/7/2 17:11
 */
public class ShiroEncryptUtil {
    //加密内容
    private static String pass = "hello shiro";
    //盐
    private static String salt = "zheshi salt";
    //加密次数
    private static int hashIterations = 3;

    /**
     * md5加密
     */
    public static void md5Test() {
        //MD5普通加密
        String encodeToString = new Md5Hash(pass).toString();
        System.out.println(encodeToString);
        //md5加密,加密内容source,带盐加密salt,还可以指定加密次数:hashIterations
        String encodeToString2 = new Md5Hash(pass, salt, hashIterations).toString();
        System.out.println(encodeToString2);
    }

    /**
     * base64
     */
    public static void base64Test() {
        String encodeToString = Base64.encodeToString(pass.getBytes());
        System.out.println(encodeToString);

        String decodeToString = Base64.decodeToString(pass);
        System.out.println(decodeToString);
    }



    /**
     * sha加密
     * SHA1,SHA256,SHA512
     */
    public static void shaTest() {
        String sha1hash = new Sha1Hash(pass, salt, hashIterations).toBase64();
        String sha256hash = new Sha256Hash(pass, salt, hashIterations).toBase64();
        String sha512hash = new Sha512Hash(pass, salt, hashIterations).toBase64();

        System.out.println(sha1hash);
        System.out.println(sha256hash);
        System.out.println(sha512hash);
    }

    /**
     * 通用加密:SimpleHash,将算法名称添加到方法即可
     */
    public static void simleHashTest() {
        // algorithmName 算法名称
        String algorithmName="md5";//sha1,sha-256,sha-512。。。,下面的第一个参数
        String encryptStr = new SimpleHash("md5", pass, salt, hashIterations).toString();
        String sha256 = new SimpleHash("sha-256", pass, salt, hashIterations).toString();
        String sha512= new SimpleHash("sha-512", pass, salt, hashIterations).toString();

        System.out.println(encryptStr);
        System.out.println(sha256);
        System.out.println(sha512);
    }

    //hex十六进制编码
    public static void hexTest() {
        String encodeToString = Hex.encodeToString(pass.getBytes());
        String decodeToString = new String(Hex.decode(encodeToString));

        System.out.println("加密:"+encodeToString);
        System.out.println("解密:"+decodeToString);
    }

    public static void main(String[] args) {
        md5Test();
        base64Test();
        shaTest();
        simleHashTest();
        hexTest();
    }
}

下面我们来看看具体操作过程。

创建用户并加密

使用shiro自带的md5加密方式对密码进行加密。

@RequestMapping("save")
public String save(SysUser sysUser){
    //通过shiro自带的Md5Hash对密码进行加密,第一个参数是密码明文,第二个参数是盐salt,第三个是加密次数
    //注意,这一块儿设置的策略要与shiroconfig里面的HashedCredentialsMatcher设置的一样,否则解密会失败
    sysUser.setPassword(new Md5Hash(sysUser.getPassword(),sysUser.getSalt(),2).toString());
    sysUserService.save(sysUser);
    return "添加成功";
}

Md5Hash有三个参数

- 第一个参数是密码明文
  - 第二个参数是盐salt
  - 第三个是加密次数

创建HashedCredentialsMatcher

在shiro的配置类ShiroConfig中,需要添加密码校验规HashedCredentialsMatcher

/**
 * Shiro自带密码管理器
 * @return
 */
@Bean("hashedCredentialsMatcher")
public HashedCredentialsMatcher getHashedCredentialsMatcher(){
    HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
    //设置加密算法的名字,shiro自带有md5等加密算法
    credentialsMatcher.setHashAlgorithmName("md5");
    //设置散列次数,2表示md5加密两次
    credentialsMatcher.setHashIterations(2);
    //加密为哈希
    credentialsMatcher.setStoredCredentialsHexEncoded(true);
    return credentialsMatcher;
}

HashedCredentialsMatcher设置加密算法未md5,加密次数为2,与我们创建用户时设置的是一样的

添加HashedCredentialsMatcher

在shiro的配置类ShiroConfig中,创建自定义MyShiroRealm的bean,并且把HashedCredentialsMatcher的bean通过setCredentialsMatcher方法设置进去。

/**
 * 创建自定义的realm
 * @param matcher
 * @return
 */
@Bean("myShiroRealm")
public MyShiroRealm myShiroRealm(HashedCredentialsMatcher matcher) {
    MyShiroRealm myShiroRealm = new MyShiroRealm();
    myShiroRealm.setAuthorizationCachingEnabled(false);
    myShiroRealm.setCredentialsMatcher(matcher);
    return myShiroRealm;
}

设置SimpleAuthenticationInfo

修改上一节中MyShiroRealmdoGetAuthenticationInfo方法

SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
                sysUser, //用户信息
                sysUser.getPassword(), //密码
                ByteSource.Util.bytes(sysUser.getSalt()),//盐salt
                getName()  //realm name
        );

主要是修改了new SimpleAuthenticationInfo的参数,上一节用了3个参数,这一节我们用4个参数,参数含义看注释就行。

测试

  • 在浏览器输入http://localhost:8088/moyundong/sysUser/save?username=water&password=123456&salt=test001添加一个用户,用户名为water,密码为123456
  • 在浏览器输入http://localhost:8088/moyundong/sysUser/login?username=water&password=123456会登录成功
  • 我们在数据库看到的密码就不是123456,而是加密后的fbdfdb1befd2ba6b5ea6b979e8305991