对明文密码进行加密是当前软件项目安全必须做的一步,而shiro作为安全框架为密码加密提供了多种配置方式。md5盐值加密是其中一种加密方式。
md5一种被广泛使用的密码散列函数,可以产生出一个128位(16字节)的散列值(hash value),用于确保信息传输完整一致。
而盐值可以由开发者自行设定,这样大大降低了密码被破译的可能性。
1. 重写doGetAuthenticationInfo方法,编写加密验证的逻辑代码
//密码加密验证
//credentialsSalt: 盐值,这里我使用的是用户名,也可以用系统当前时间或其他
ByteSource credentialsSalt = ByteSource.Util.bytes(user.getName());
//Shiro会将用户输入的密码先进行MD5盐值加密再进行比较
return new SimpleAuthenticationInfo(user,user.getPwd(),credentialsSalt,getName());
SimpleAuthenticationInfo方法的源码:
public SimpleAuthenticationInfo(Object principal, Object hashedCredentials, ByteSource credentialsSalt, String realmName) {
this.principals = new SimplePrincipalCollection(principal, realmName);
this.credentials = hashedCredentials;
this.credentialsSalt = credentialsSalt;
}
2. 修改Shiro配置,自定义加密方法
//创建 realm 对象
@Bean
public UserRealm userRealm(@Qualifier("hashedCredentialsMatcher") HashedCredentialsMatcher matcher){
UserRealm userRealm = new UserRealm();
//替换当前的Realm 的 CredentialsMatcher 属性,
userRealm.setCredentialsMatcher(matcher);
return userRealm;
}
//设置加密算法
@Bean("hashedCredentialsMatcher")
public HashedCredentialsMatcher hashedCredentialsMatcher(){
HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
//指定加密方式为MD5
credentialsMatcher.setHashAlgorithmName("MD5");
//hash加密次数
credentialsMatcher.setHashIterations(1024);
return credentialsMatcher;
}
3. 数据库中的密码应是加密后的密码
在数据库中存储的密码应该是md5盐值加密后的密码。为此我们可以编写一个工具类,将密码先行通过加密得到,再存入数据库。
public class PasswordGenerateUtil {
public String getPassword(String username, String password){
// 与在ShiroConfig设置的一样
ByteSource salt = ByteSource.Util.bytes(username);
int hashTimes = 1024;
Md5Hash md5Hash = new Md5Hash(password, salt, hashTimes);
return md5Hash.toString();
}
}
用一个测试类获取密码
@Test
void contextLoads() {
PasswordGenerateUtil passwordGenerateUtil = new PasswordGenerateUtil();
String username = "root";
String password = "123456";
System.out.println("加密后的密码:" + passwordGenerateUtil.getPassword(username, password));
}