shiro之密码加密和密码对比 重写setCredentialsMatcher()方法 重写doGetAuthenticationInfo()认证方法 查看密码加密和密码对比

密码加密登录是为了提高系统安全性,即使是管理员查看数据库也得不到密码。

用户在登录时所输入的密码都是明文的,数据库中存的密码是明文加密之后的,因此就必须将用户输入之后的密码进行加密再去跟数据库进行对比。

而且还要求这个加密算法是不可逆的,即由加密后的字符串不能反推回来原来的密码,如果能反推回来那这个加密是没有意义的。其中MD5是目前比较可靠的不可逆的加密方式,因此我们可以通过MD5来对密码进行加密。

重写setCredentialsMatcher()方法

在 Realm 类中重写setCredentialsMatcher()方法,此方法用于设置加密码算法:

1
2
3
4
5
6
7
@Override
public void setCredentialsMatcher(CredentialsMatcher credentialsMatcher) {
HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
hashedCredentialsMatcher.setHashAlgorithmName("md5");//md5加密方式
hashedCredentialsMatcher.setHashIterations(1024);//加密次数
super.setCredentialsMatcher(hashedCredentialsMatcher);
}

该方法中使用的是 HashedCredentialsMatcher 类设置加密算法,此处设置的是md5加密方式和加密次数1024次。设置完上面的密码匹配类之后,就可以将用户的登录密码自动加密为MD5。

注:别忘了改super.setCredentialsMatcher()里面的参数是hashedCredentialsMatcher。

重写doGetAuthenticationInfo()认证方法

在 Realm 类中重写 doGetAuthenticationInfo() 认证方法,该方法用于认证,可以对登录时所输入的密码进行加密加盐:

什么是盐:并不是炒菜的调料,而是为了提高加密的安全性,简单来说就是:MD5加密之后再进行了一层加密。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/**
* 重写的自定义认证方法
* @param authenticationToken 该认证Token对象封装了用户名、密码等信息
* @return 认证信息
* @throws AuthenticationException
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken)
throws AuthenticationException {
//认证Token转换为常用的用户名和密码Token
UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
User user = userService.findByUserName(token.getUsername());
if (user == null)
return null;//抛出用户不存在
//该盐值可以是已经存在数据库中的盐值字段,也可以是当前用户名(但不推荐),一般盐值都是唯一不变的字段
ByteSource salt = ByteSource.Util.bytes(user.getSalt());
String credential = user.getPassword();
return new SimpleAuthenticationInfo(
user, //用户对象
credential, //用户密码
salt, //用户盐值,如果不想加盐即可省略该参数
this.getName());
}

查看密码加密和密码对比

因为我们用的是MD5加密方式,那么按两下Shift键搜索 HashedCredentialsMatcher 类,找到 doCredentialsMatch() 方法,该方法中就进行了密码加密和密码对比。

在 doCredentialsMatch() 方法中打个断点进行进行调试,可以看到下图中的结果:

upload successful

结论:MD5加密方式的密码加密和密码对比都是在 HashedCredentialsMatcher 类中的 doCredentialsMatch() 方法进行的。