前言
最近用到Shiro安全框架,做加密验证的时候遇到一些问题,对Shiro内部登录验证流程有些疑惑,网上的多数Shiro的环境搭建只是简单的明文密码匹配,甚至有些文章的注释也不尽正确。在这里记录下通过分析源码的整理。
大纲
- 使用Shiro提供的类进行密码加密
- 登录验证的流程
使用Shiro提供的类进行密码加密
Shiro提供了org.apache.shiro.crypto.hash.SimpleHash
加密类继承了org.apache.shiro.crypto.hash.AbstractHash
,先看看它主要的构造方法:
/*
参数说明:
String algorithmName :加密算法
Object source :待加密的对象,字符串等
Object salt :盐,混入待加密的密码进行加密,加大破解难度
int hashIterations :加密次数
*/
public SimpleHash(String algorithmName, Object source)
public SimpleHash(String algorithmName, Object source, Object salt)
public SimpleHash(String algorithmName, Object source, Object salt, int hashIterations)
由构造方法可知,SimpleHash可以自主指定加密算法,MD5、SHA-256、SHA-512等等,Shiro在同包下,对SimpleHash进一步封装出Md5Hash、Sha256Hash等方便使用。例如Sha256Hash 继承了SimpleHash ,实际上就是指定了algorithmName为”SHA-256”的SimpleHash。
public class Sha256Hash extends SimpleHash {
public static final String ALGORITHM_NAME = "SHA-256";
public Sha256Hash() {
super("SHA-256");
}
public Sha256Hash(Object source) {
super("SHA-256", source);
}
public Sha256Hash(Object source, Object salt) {
super("SHA-256", source, salt);
}
public Sha256Hash(Object source, Object salt, int hashIterations) {
super("SHA-256", source, salt, hashIterations);
}
public static Sha256Hash fromHexString(String hex) {
Sha256Hash hash = new Sha256Hash();
hash.setBytes(Hex.decode(hex));
return hash;
}
public static Sha256Hash fromBase64String(String base64) {
Sha256Hash hash = new Sha256Hash();
hash.setBytes(Base64.decode(base64));
return hash;
}
}
问题来了,现在算法、原密码字符串和加密次数都确定了,如何获取盐呢?
为了确保安全性,盐值不应重复,每次修改密码要产生不同的盐值。首先想到的是使用java.util.Random
来获得随机数,然而Random使用 LCG 算法生成随机数,不建议使用在信息安全应用中,应使用java.security.SecureRandom
产生不可预知的盐值:
SecureRandom random = SecureRandom.getInstance("SHA1PRNG");//使用SHA1PRNG算法
String salt = String.va