Shiro密码加盐

在有“密码加盐”方法之前,一般做法是直接对密码进行散列,理论上散列值不可逆,但黑客或者内部人士在获取密码散列值后,再通过查散列值字典(例如MD5密码破解网站),就可能知道对应的密码明文。
通过加盐处理,可以实现相同的密码明文,产生不同的密码值,减少被破解的风险。
shiro支持密码加密,或不加密。与ShiroConfig.hashedCredentialsMatcher方法密切相关。
在上篇【Spring Boot中引入Jpa和Shiro】的基础上进行密码加盐。
JpaController.java 在add方法中,增加密码加盐逻辑

@GetMapping(path = "/jpa/add")
public String addNewUser(@RequestParam String name,
		@RequestParam String username, @RequestParam String password) {
	JpaUser user = new JpaUser();
	user.setName(name);
	user.setUsername(username);
	
	// uuid获取随机字符串,作为盐值。
	String salt = StringUtil.getUUID();
	user.setSalt(salt);
	//add Salt to password
	//user.getCredentialsSalt我没有直接使用盐,而是将用户名和盐作为密码加密的最终盐值
	SimpleHash hash = new SimpleHash(hcm.getHashAlgorithmName(),
			password, user.getCredentialsSalt(), hcm.getHashIterations());
	//重新赋值
	user.setPassword(hash.toString());
	
	userRepository.save(user);
	
	//重定向到 根目录index
	return "redirect:/index";
}

MyShiroRealm.java 生成SimpleAuthenticationInfo实例时,使用加盐处理

public AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token)
		throws AuthenticationException {
	String username = (String) token.getPrincipal();
	JpaUser userInfo = null;
	List<JpaUser> userInfoList = userRepository.findByUsername(username);
	if (userInfoList == null) {
		return null;
	} else if (userInfoList.size() <= 0) {
		return null;
	} else {
		userInfo = userInfoList.get(0);
	}

	SimpleAuthenticationInfo authInfo = new SimpleAuthenticationInfo(
			userInfo, 
			userInfo.getPassword(),
			//salt=username+salt
			ByteSource.Util.bytes(userInfo.getCredentialsSalt()),
			getName() // realm name
	);

	return authInfo;
}

StringUtil.java 获取随机字符串工具类

public class StringUtil {
	public static String getUUID() {
		String uuid = UUID.randomUUID().toString();
		// 去掉字符串中的"-"符号
		uuid = uuid.replaceAll("-", "");
		return uuid;
	}
	/**
	 * 生成指定长度的随机字符串(0-9a-zA-Z)
	 */
	public static String getRandomString(int length) {
		// 产生随机数
		Random random = new Random();
		StringBuffer sb = new StringBuffer();
		// 循环length次
		for (int i = 0; i < length; i++) {
			// 产生0-2个随机数,既与a-z,A-Z,0-9三种可能
			int number = random.nextInt(3);
			long result = 0;
			switch (number) {
			// 如果number产生的是数字0;
			case 0:
				// 产生A-Z的ASCII码
				result = Math.round(Math.random() * 25 + 65);
				// 将ASCII码转换成字符
				sb.append(String.valueOf((char) result));
				break;
			case 1:
				// 产生a-z的ASCII码
				result = Math.round(Math.random() * 25 + 97);
				sb.append(String.valueOf((char) result));
				break;
			case 2:
				// 产生0-9的数字
				sb.append(String.valueOf(new Random().nextInt(10)));
				break;
			}
		}
		return sb.toString();
	}
}

猜你喜欢

转载自blog.csdn.net/weixin_44153121/article/details/86512355