【源码解析】Spring Boot中Security关于BCryptPasswordEncoder的使用

前言

        SpringSecurity中有一个升级版的消息--BCryptPasswordEncoder,使用相同的明文,生成的新的加密字符串都是不一样的,这与我们常见的加密算法MD5是不同的,MD5加密的话,只要是相同的salt和原密码,加密后产生的密串都是一致的。

关于MD5

        MD5的典型应用是对一段信息(Message)产生信息摘要(Message-Digest),以防止被篡改。比如,在UNIX下有很多软件在下载的时候都有一个文件名相同,文件扩展名为.md5的文件,在这个文件中通常只有一行文本,大致结构如: 
  MD5 (tanajiya.tar.gz) = 0ca175b9c0f726a831d895e269332461 
  这就是tanajiya.tar.gz文件的数字签名。MD5将整个文件当作一个大文本信息,通过其不可逆的字符串变换算法,产生了这个唯一的MD5信息摘要。为了让读者朋友对MD5的应用有个直观的认识,笔者以一个比方和一个实例来简要描述一下其工作过程: 
  大家都知道,地球上任何人都有自己独一无二的指纹,这常常成为公安机关鉴别罪犯身份最值得信赖的方法;与之类似,MD5就可以为任何文件(不管其大小、格式、数量)产生一个同样独一无二的“数字指纹”,如果任何人对文件名做了任何改动,其MD5值也就是对应的“数字指纹”都会发生变化。 
  我们常常在某些软件下载站点的某软件信息中看到其MD5值,它的作用就在于我们可以在下载该软件后,对下载回来的文件用专门的软件(如Windows MD5 Check等)做一次MD5校验,以确保我们获得的文件与该站点提供的文件为同一文件。利用MD5算法来进行文件校验的方案被大量应用到软件下载站、论坛数据库、系统文件安全等方面。 

可以通过一些在线工具对123456进行MD5加密,多次对123456加密的结果其实都是一样的。

关于BCryptPasswordEncoder

       Spring Security提供了BCryptPasswordEncoder这个加密算法类,实现Spring的PasswordEncoder接口使用BCrypt强哈希方法,对密码进行加密。生成的字符串可以长达60位,比MD5有着不小的优势,而且MD5也不再是Spring Security推荐的加密算法了。

       我们可以在用户信息类new一个BCryptPasswordEncoder,进行加密。

BCryptPasswordEncoder Encoder = new BCryptPasswordEncoder();
String newPwd= Encoder.encode(password);

      其中,newPwd为加密之后的密串。下面两张图中的$开头的字符串都是1234qwer加密后的密串。

       也就是说,同样的密码在BCryptPasswordEncoder的加密后,其产生的密串是不同的,那么我们之前采用MD5加密的时候,对密码的匹配都是拿加密后的密串进行对比,在此刻就不通用了。

       BCryptPasswordEncoder有自己独特的比较方法,通过阅读源码可以知道,其对比密码采用的是matches这个方法。只要将原密码和任意一个加密后的密串进行matches,根据返回的Boolean值来判断是否一致。

	public String encode(CharSequence rawPassword) {
		String salt;
		if (strength > 0) {
			if (random != null) {
				salt = BCrypt.gensalt(strength, random);
			}
			else {
				salt = BCrypt.gensalt(strength);
			}
		}
		else {
			salt = BCrypt.gensalt();
		}
		return BCrypt.hashpw(rawPassword.toString(), salt);
	}

	public boolean matches(CharSequence rawPassword, String encodedPassword) {
		if (encodedPassword == null || encodedPassword.length() == 0) {
			logger.warn("Empty encoded password");
			return false;
		}

		if (!BCRYPT_PATTERN.matcher(encodedPassword).matches()) {
			logger.warn("Encoded password does not look like BCrypt");
			return false;
		}

		return BCrypt.checkpw(rawPassword.toString(), encodedPassword);
	}

 相当于帮我们做了一层gensalt的过程

最后

        生命不止,学习不息,笔耕不辍!

发布了21 篇原创文章 · 获赞 15 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/lkh5201314/article/details/100051474