散列算法一般用于生成一段文本的摘要信息,散列算法不可逆,将内容可以生成摘要,无法将摘要转成原始内容。散列算法常用于对密码进行散列,常用的散列算法有MD5、SHA。
一般散列算法需要提供一个salt(盐)与原始内容生成摘要信息,这样做的目的是为了安全性,比如:111111的md5值是:96e79218965eb72c92a549dd5a330112,拿着“96e79218965eb72c92a549dd5a330112”去md5破解网站很容易进行破解,如果要是对111111和salt(盐,一个随机数)进行散列,这样虽然密码都是111111加不同的盐会生成不同的散列值。
Md5散列源码
散列示例
public class Md5Util { private static final String PASSWROD="111111"; //要加密的明文 private static final String SALT = "tdit";//盐 private static final int HASHITERATIONS=2;//加密次数 @Test public void md5Test() { //96e79218965eb72c92a549dd5a330112 Md5Hash md5Hash = new Md5Hash(Md5Util.PASSWROD); String passwordMd5 = md5Hash.toString(); System.out.println(passwordMd5); } /** * md5加Salt加密 */ @Test public void md5SaltTest() { //5969345e633667bbf5f5102c179a2d67 Md5Hash md5Hash = new Md5Hash(PASSWROD,SALT); String passwordMd5 = md5Hash.toString(); System.out.println(passwordMd5); } /** * md5加Salt 散列次数 */ @Test public void md5SaltIterationsTest() { //111111加盐散列2次: 21f2a979da49e3fa35dc6a16467b1483 //simpleHash : 21f2a979da49e3fa35dc6a16467b1483 Md5Hash md5Hash = new Md5Hash(PASSWROD,SALT,HASHITERATIONS); String passwordMd5 = md5Hash.toString(); System.out.println(passwordMd5); } @Test public void SimpleHashSaltIterationsTest() { String string = new SimpleHash("md5",PASSWROD,SALT,HASHITERATIONS).toString(); System.out.println(string); } }
在realm中使用
实际应用是将盐和散列后的值存在数据库中,自动realm从数据库取出盐和加密后的值由shiro完成密码校验。
自定义realm
@Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token){ //获取认证凭证 UsernamePasswordToken upToken = (UsernamePasswordToken) token; String username = upToken.getUsername(); // Null username is invalid if (username == null) { throw new AccountException("账号不能为空"); } SimpleAuthenticationInfo info = null; //模拟数据库获取数据 Map<String,Object> data = new HashMap<String,Object>(); //原始密码111111 //md5加盐散列2次密码21f2a979da49e3fa35dc6a16467b1483 data.put("zhangsan", "21f2a979da49e3fa35dc6a16467b1483"); data.put("lisi", "21f2a979da49e3fa35dc6a16467b1483"); data.put("wang", "21f2a979da49e3fa35dc6a16467b1483"); //通过数据库获取username的信息 Object userPassword = data.get(username); if (userPassword ==null) { return null; } if (userPassword == null) { throw new UnknownAccountException("密码错误"); } info = new SimpleAuthenticationInfo(username, userPassword,ByteSource.Util.bytes("tdit"), getName()); return info; }
realm配置
默认凭证匹配器进行密码匹配的源码流程
现在我们使用md5进行加密,所以需要指定(配置)使用的匹配器
在这里可以直接使用md5
配置shiro-cryptography.ini
[main] #定义凭证匹配器 credentialsMatcher=org.apache.shiro.authc.credential.HashedCredentialsMatcher #散列算法 credentialsMatcher.hashAlgorithmName=md5 #散列次数 credentialsMatcher.hashIterations=2 #将凭证匹配器设置到realm customRealm=com.td.shiro.realm.CustomRealmMd5 customRealm.credentialsMatcher=$credentialsMatcher securityManager.realms=$customRealm