此篇文章是在Shiro整合Spring Boot入门的基础上写的,如果你没有shiro基础看不懂的话,可以去看看。
1、给Realm添加CredentialsMatcher
@Bean
public UserRealm userRealm() {
UserRealm userRealm = new UserRealm();
// 设置加密算法
HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher("md5");
// 设置加密次数
credentialsMatcher.setHashIterations(1);
userRealm.setCredentialsMatcher(credentialsMatcher);
return userRealm;
}
在身份认证期间,Shiro会尝试使用credentialsMatcher去比对用户名密码是否正确。
2、保存在数据库中的密码也需要是加密后的密码
public class UserRealm extends AuthorizingRealm {
// 模拟数据库中的数据
private Map<String, User> users = new HashMap<>();
{
// Realm中方法的密码必须也是加密过得
String password = new SimpleHash("md5", "123", "salt").toString();
users.put("xiaowang", new User("xiaowang", password, "user:add,user:update"));
users.put("xiaoming", new User("xiaoming", password, "user:update"));
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
System.out.println("执行了认证=>doGetAuthenticationInfo");
UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
// 模拟从数据库中根据用户名查用户信息
User user = users.get(token.getUsername());
if (user == null) {
throw new UnknownAccountException();
}
// 返回AuthenticationInfo中,还需要携带盐值
return new SimpleAuthenticationInfo(user, user.getPassword(), ByteSource.Util.bytes("salt"), "");
}
。。。
}
这里说明一下,为什么AuthenticationInfo要携带盐值。其实Shiro的比对规则是这样的,对用户输入的密码进行加密,然后与数据库中的密文进行比对,判断其是否相等。
所以有加盐的话,Shiro就需要知道盐是什么,而这个盐就从AuthenticationInfo获取。
最后来一个credentialsMatcher的使用案例:
public static void main(String[] args) {
// 密码匹配器
HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher("md5");
// 设置加密次数
credentialsMatcher.setHashIterations(1);
// 模拟用户登录输入的用户名密码
UsernamePasswordToken token = new UsernamePasswordToken("xiaowang", "123");
// 模拟从Realm中获取的认证信息
String password = new SimpleHash("md5", "123").toString();
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo("xiaowang", password, "");
// 使用比较器比较
System.out.println(credentialsMatcher.doCredentialsMatch(token, info));
// 加盐
password = new SimpleHash("md5", "123", "salt").toString();
info = new SimpleAuthenticationInfo("xiaowang", password, ByteSource.Util.bytes("salt"), "");
System.out.println(credentialsMatcher.doCredentialsMatch(token, info));
}