版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_34598667/article/details/84642279
散列算法
通常要对密码进行散列,常用的有md5、sha等。
对MD5加密,如果知道散列后的值可以通过穷举法,得到MD5密码对应的明文。建议对MD5进行散列时加salt(盐),进行加密相当于对原始密码+盐 进行散列。
正常使用时散列方法:
在程序中对原始密码+盐进行散列,将散列值存储到数据库中,并且还要将盐也要存储在数据库中。
如果进行密码对比时,使用相同方法,将原始密码+盐进行散列,进行对比。
MD5散列测试程序
public class MD5Test {
public static void main(String[] args) {
//原始密码
String source="123456";
//盐
String salt="qwerty";
//散列次数
int hashInterrations=2;
/* 方法1:
* 第一个参数:明文,原始密码
* 第二个参数:盐,通常使用随机数,这里指定固定字符串
* 第三个参数:散列的次数,比如散列两次,相当 于md5(md5(''))
*/
Md5Hash md5Hash=new Md5Hash(source, salt, hashInterrations);
System.out.println(md5Hash);
//方法2:第一个参数:散列算法
SimpleHash sim=new SimpleHash("md5", source, salt,hashInterrations);
System.out.println(sim);
}
}
运行测试:
78f50b64a132f209ea77fdeebe501de6
78f50b64a132f209ea77fdeebe501de6
自定义realm支持散列算法
需求:实际开发时realm要进行md5值(明文散列后的值)的对比
@Override
protected AuthenticationInfo doGetAuthenticationInfo(
AuthenticationToken token) throws AuthenticationException {
//token是用户输入的
//1、从token中取出身份信息
String userCode=(String) token.getPrincipal();
//2、根据用户输入的userCode从数据库查询
//假设数据库用户是张三
//如果查询不到则返回null
/*if(!userCode.equals("zs")){
return null;
}*/
//模拟从数据库查到密码,散列值(取上面测试生成的散列码)
String pwd="78f50b64a132f209ea77fdeebe501de6";
// 模拟从数据库获取salt
String salt = "qwerty";
//上边散列值和盐对应的明文:123
//如果查询到则返回认证信息AuthenticationInfo
SimpleAuthenticationInfo simpleAuthenticationInfo=new SimpleAuthenticationInfo(
userCode,pwd,ByteSource.Util.bytes(salt),this.getName());
return simpleAuthenticationInfo;
}
在realm中配置凭证匹配器
[main]
[main]
#定义凭证匹配器
credentialsMatcher=org.apache.shiro.authc.credential.HashedCredentialsMatcher
#散列算法
credentialsMatcher.hashAlgorithmName=md5
#散列次数
credentialsMatcher.hashIterations=2
#自定义realm
customRealm=com.oak.shiro.CustomRealm
#将realm设置到securityManager,相当于Spring注入
securityManager.realms=$customRealm
customRealm.credentialsMatcher=$credentialsMatcher
测试:
@Test
public void testLoginAndLogout(){
//创建securityManager工厂,通过ini配置文件创建securityManager工厂
Factory<SecurityManager> factory=new IniSecurityManagerFactory("classpath:shiro-realm.ini");
//创建SecurityManager
SecurityManager securityManager=factory.getInstance();
//将securityManager设置到当前运行环境中
SecurityUtils.setSecurityManager(securityManager);
//从SecurityUtils里边创建一个subject
Subject subject = SecurityUtils.getSubject();
//在认证提交前准备token(令牌)
UsernamePasswordToken token=new UsernamePasswordToken("admin","123");
//执行认证提交--认证失败
subject.login(token);
//是否认证通过
boolean isAuthenticated =subject.isAuthenticated();
System.out.println("是否认证通过:"+isAuthenticated);
//退出操作
subject.logout();
//是否认证通过
isAuthenticated=subject.isAuthenticated();
System.out.println("是否认证通过:"+isAuthenticated);
}
测试:
是否认证通过:true
是否认证通过:false