1,散列算法概述
散列算法一般用于生成数据的摘要信息,是一种不可逆的算法,一般适合存储密码之类的数据,常见的散列算法如MD5、SHA等。一般进行散列时最好提供一个salt(盐),比如
加密密码“admin”,产生的散列值是“21232f297a57a5a743894a0e4a801fc3”,可以到一
些md5 解密网站很容易的通过散列值得到密码“admin”,即如果直接对密码进行散列相
对来说破解更容易,此时我们可以加一些只有系统知道的干扰数据,如用户名和ID(即盐);
这样散列的对象是“密码+用户名+ID”,这样生成的散列值相对来说更难破解。
2,MD5算法
public class ShiroTest {
//shiro提供了现成的加密类 Md5Hash
@Test
public void testMd5(){
//MD5加密
String password = new Md5Hash("1111").toString();
System.out.println("加密后:"+password);
//加盐 salt 默认一次散列
String password_salt=new Md5Hash("1111", "laolei").toString();
System.out.println("加盐后:"+password_salt);
//散列2次
String password_salt_2 = new Md5Hash("1111", "laolei", 2).toString();
System.out.println("散列2次:"+password_salt_2);
//使用SimpleHash
SimpleHash hash = new SimpleHash("MD5", "1111", "laolei", 2);
System.out.println("simpleHash:"+hash.toString());
}
}
3,在自定义Realm中使用散列
Realm实现代码
public class UserRealm extends AuthorizingRealm {
@Override
public String getName() {
return "UserRealm";
}
//用于认证
@Override
protected AuthenticationInfo doGetAuthenticationInfo(
AuthenticationToken token) throws AuthenticationException {
//从token中获取身份信息
String username = (String)token.getPrincipal();
//根据用户名到数据库中取出用户信息 如果查询不到 返回null
//按照固定规则加密码结果 ,此密码 要在数据库存储,原始密码 是1111,盐是laolei 2次散列
String password = "1620d20433da92e2523928e351e90f97";//假如从数据库中获取密码为1111
//返回认证信息
SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(username,
password, ByteSource.Util.bytes("laolei"),this.getName());
return simpleAuthenticationInfo;
}
//用于授权
@Override
protected AuthorizationInfo doGetAuthorizationInfo(
PrincipalCollection principals) {
return null;
}
}
4, Realm配置
Shiro.ini 在配置文件中,需指定凭证匹配器
[main]
#定义凭证匹配器
credentialsMatcher=org.apache.shiro.authc.credential.HashedCredentialsMatcher
#散列算法
credentialsMatcher.hashAlgorithmName=md5
#散列次数
credentialsMatcher.hashIterations=2
#将凭证匹配器设置到realm
userRealm=com.sxt.realm.UserRealm
userRealm.credentialsMatcher=$credentialsMatcher
securityManager.realms=$userRealm
5, 测试
public static void main(String[] args) {
//得到工厂
Factory<SecurityManager> factory=new IniSecurityManagerFactory();
//创建SecurityManager
SecurityManager securityManager=factory.getInstance();
//把SecurityManager绑定到运行环境
SecurityUtils.setSecurityManager(securityManager);
//创建主体
Subject subject=SecurityUtils.getSubject();
//创建Token用于验证
UsernamePasswordToken token=new UsernamePasswordToken("zhangsan", "123");
try {
//认证
subject.login(token);
System.out.println(subject.isAuthenticated());
} catch (UnknownAccountException e) {
System.out.println("用户名不存在");
}catch (IncorrectCredentialsException e) {
System.out.println("密码不正确");
}
}