1.先写一个shiro的密码生成工具
package com.learning.www.shiro.config;
import org.apache.shiro.crypto.hash.SimpleHash;
public class ShiroEncryption {
/***
* 对用户的密码进行MD5加密
* 做成工具类
*/
public static String shiroEncryption(String password,String salt) {
// shiro 自带的工具类生成salt
//String salt = new SecureRandomNumberGenerator().nextBytes().toString();
// 加密次数
int times = 2;
// 算法名称
String algorithmName = "md5";
String encodedPassword = new SimpleHash(algorithmName,password,salt,times).toString();
// 返回加密后的密码
return encodedPassword;
}
}
2.在每次添加用户的时候,进行加密加盐处理
@Override
public int postUserInfo(User user) {
// shiro 自带的工具类生成salt
String salt = new SecureRandomNumberGenerator().nextBytes().toString();
String encodedPassword = ShiroEncryption.shiroEncryption(user.getPassword(),salt);
user.setSalt(salt);
user.setPassword(encodedPassword);
return userMapper.postUserInfo(user);
}
3.在shiroConfig中,需要加入匹配验证凭证代码
/***
* shiro的在进行密码验证的时候,将会在此进行匹配
* @return
*/
@Bean("hashedCredentialsMatcher")
public HashedCredentialsMatcher hashedCredentialsMatcher() {
HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
hashedCredentialsMatcher.setHashAlgorithmName("md5");// 散列算法:这里使用MD5算法;
hashedCredentialsMatcher.setHashIterations(2);// 散列的次数,比如散列两次,相当于md5(md5(""));
//hashedCredentialsMatcher.setStoredCredentialsHexEncoded(true);// 表示是否存储散列后的密码为16进制,需要和生成密码时的一样,默认是base64;
return hashedCredentialsMatcher;
}
4.在realm中,修改doGetAuthenticationInfo函数,返回用户身份信息实例,返回的SimpleAuthenticationInfo中包含4个参数:
Parameters:(括号中是我的理解哈~)
principal the 'primary' principal associated with the specified realm.(token中的身份信息,username)
hashedCredentials the hashed credentials that verify the given principal.(token中的身份信息,password)
credentialsSalt the salt used when hashing the given hashedCredentials(salt值,这边需要处理一下)
realmName the realm from where the principal and credentials were acquired.(使用的哪个realm,就用哪个名字)
/**
* 获取身份验证信息
* Shiro中,最终是通过 Realm 来获取应用程序中的用户、角色及权限信息的。
*
* @param authenticationToken 用户身份信息 token
* @return 返回封装了用户信息的 AuthenticationInfo 实例
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
System.out.println("————身份认证方法————");
UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
User user = usermapperservice.getPasswordByUsername(token.getUsername());
String oringnPassword = new String((char[]) token.getCredentials());
String salt = user.getSalt();
System.out.println(token.getUsername()+"===="+oringnPassword);
String encodedPassword = ShiroEncryption.shiroEncryption(oringnPassword,salt);
System.out.println("密码:"+encodedPassword);
//String password = null;
// 从数据库获取对应用户名密码的用户
// usermapperservice.getPasswordByUsername(token.getUsername()).getPassword() --> 获取用户名对应的密码
if (null == usermapperservice.getPasswordByUsername(token.getUsername())) {
throw new AccountException("用户名不正确");
} else if (!(usermapperservice.getPasswordByUsername(token.getUsername()).getPassword()).equals(encodedPassword)) {
throw new AccountException("密码不正确");
}else {
//password = usermapperservice.getPasswordByUsername(token.getUsername()).getPassword();
}
return new SimpleAuthenticationInfo(user.getUsername(), oringnPassword, ByteSource.Util.bytes(salt) , getName());
}
我的理解可能有点问题哈,希望有问题的地方可以帮我指出来~谢谢!
外附密码匹配流程的博客(感谢博主):https://blog.csdn.net/hxm_code/article/details/50136173