一般来说,实际项目中隐私数据没有在网络上明文跑路,都会采用不同的加密算法。Shiro中的认证凭据通常也会采用算法进行加密。
该接口只有一个方法,doCredentialsMatch,就是用来进行密码比较的!
源码如下:
public interface CredentialsMatcher {
/**
* Returns {@code true} if the provided token credentials match the stored account credentials,
* {@code false} otherwise.
*
* @param token the {@code AuthenticationToken} submitted during the authentication attempt
* @param info the {@code AuthenticationInfo} stored in the system.
* @return {@code true} if the provided token credentials match the stored account credentials,
* {@code false} otherwise.
*/
boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info);
}
其实现类如下:
里面可以看到我们常用的MD5算法和SHA-X算法。
其中Md5CredentialsMatcher 和Sha1CredentialsMatcher 标注已经过时,通常我们会直接在容器中注册HashedCredentialsMatcher来使用!
如这里我们注册HashedCredentialsMatcher并指定算法为Md5,xml配置如下:
使用【1】中的配置情况下,如果两个人的原始密码一样,那么其加密后的密码也相同,同样存在风险。
在HashedCredentialsMatcher中有这样一个方法:
protected Hash hashProvidedCredentials(Object credentials, Object salt, int hashIterations) {
String hashAlgorithmName = assertHashAlgorithmName();
return new SimpleHash(hashAlgorithmName, credentials, salt, hashIterations);
}
其中new SimpleHash(hashAlgorithmName, credentials, salt, hashIterations)
就是根据提供的原始凭据,加密算法,盐值和加密次数进行加密并返回加密后的结果。盐值是一个唯一字符串,这里你可以使用loginName作为加密盐值。
步骤如下:
SimpleAuthenticationInfo(principal, credentials, credentialsSalt, realmName)
构造器;如果使用盐值加密,我们的doGetAuthenticationInfo修改如下:
@Override
protected AuthenticationInfo doGetAuthenticationInfo(
AuthenticationToken authenticationToken) throws AuthenticationException {
UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
//获取页面传来的用户账号
String loginName = token.getUsername();
//根据登录账号从数据库查询用户信息
SysUser user = sysUserService.getUserByLoginCode(loginName);
System.out.println("从数据库查询到的用户信息 : "+user);
//一些异常新娘西
if (null == user) {
throw new UnknownAccountException();//没找到帐号
}
if (user.getStatus()==null||user.getStatus()==0) {
throw new LockedAccountException();//帐号被锁定
}
//其他异常...
//返回AuthenticationInfo的实现类SimpleAuthenticationInfo
// return new SimpleAuthenticationInfo(user, user.getPassword(), this.getName());
//盐值加密
ByteSource credentialsSalt = ByteSource.Util.bytes(loginName);
return new SimpleAuthenticationInfo(user, user.getPassword(), credentialsSalt, this.getName());
}