徐州北大青鸟
当前位置: 主页 > 学在青鸟 > 编程技巧 >

如何实现SpringSecurity中的密码加密?

时间:2021-10-25 11:20来源:未知 作者:代码如诗 点击:
Spring Security作为一个安全框架,其中必然就应该带有安全加密方面的内容,今天就带各位来学习Spring Security中的密码加密机制。 一. 密码加密简介 1. 散列加密概述 我们开发时进行密码
Spring Security作为一个安全框架,其中必然就应该带有安全加密方面的内容,今天就带各位来学习Spring Security中的密码加密机制。
 
一. 密码加密简介
 
1. 散列加密概述
 
我们开发时进行密码加密,可用的加密手段有很多,比如对称加密、非对称加密、信息摘要等。在一般的项目里,常用的就是信息摘要算法,也可以被称为散列加密函数,或者称为散列算法、哈希函数。
 
这是一种可以从任何数据中创建数字“指纹”的方法,常用的散列函数有 MD5 消息摘要算法、安全散列算法(Secure Hash Algorithm)等。
 
2. 散列加密原理
 
散列函数通过把消息或数据压缩成摘要信息,使得数据量变小,将数据的格式固定下来,然后将数据打乱混合,再重新创建成一个散列值,从而达到加密的目的。
 
散列值通常用一个短的随机字母和数字组成的字符串来代表,一个好的散列函数在输入域中很少出现散列冲突。在散列表和数据处理时,如果我们不抑制冲突来区别数据,会使得数据库中的记录很难找到。
 
但是仅仅使用散列函数还不够,如果我们只是单纯的使用散列函数而不做特殊处理,其实是有风险的!比如在两个用户密码明文相同时,生成的密文也会相同,这样就增加了密码泄漏的风险。
 
所以为了增加密码的安全性,一般在密码加密过程中还需要“加盐”,而所谓的“盐”可以是一个随机数,也可以是用户名。”加盐“之后,即使密码的明文相同,用户生成的密码密文也不相同,这就可以极大的提高密码的安全性。
 
传统的加盐方式需要在数据库中利用专门的字段来记录盐值,这个字段可以是用户名字段(因为用户名唯一),也可以是一个专门记录盐值的字段,但这样的配置比较繁琐。
 
3. Spring Security中的密码处理方案
 
那么在Spring Security中,对密码是怎么进行处理的呢?其实Spring Security对密码的处理方案,有如下3种方式:
 
对密码进行明文处理,即不采用任何加密方式;
 
采用MD5加密方式;
 
采用哈希算法加密方式。
 
3. BCryptPasswordEncoder简介
 
以上说的是3种密码处理方案,并不代表只有3种加密算法,这个请大家注意哦!
 
我们开发时,用户表中的密码通常是使用MD5等不可逆算法加密后存储,但为了防止彩虹表破解,可以先使用一个特定的字符串(如域名)进行加密,然后再使用一个随机的salt(盐值)加密。其中特定的字符串是程序代码中固定的,salt是每个密码单独随机的,我们一般会给用户表加一个字段单独存储,但这样比较麻烦。
 
而BCrypt算法却可以随机生成salt并混入最终加密后的密码,验证时也无需单独提供之前的salt,从而无需单独处理salt。不同于 Shiro 中需要自己处理密码加盐,在 Spring Security 中,BCrypt Password Encoder 本身就自带了盐,所以处理起来非常方便。
 
另外BCryptPasswordEncoder使用BCrypt强哈希函数,我们在使用时可以选择提供strength和SecureRandom参数。strength值(取值在4~31之间,默认为10)越大,则密钥的迭代次数就越多,密钥迭代次数为2^strength。
 
二. 利用BCryptPasswordEncoder进行加密
 
了解了这些基本的理论知识之后,壹哥 就带各位进行代码实现啦。
 
我们继续在之前的案例基础之上进行本案例的代码实现,所以项目创建过程略过,请参考之前的章节内容。
 
1. 编写register接口
 
为了方便测试,我们首先在UserController中编写一个register接口,用于注册一个新用户,在添加用户时对密码进行加密。
 
2. 配置密码加密算法
 
接下来我们在Security Config配置类中,配置到底该采用哪种密码加密算法。我们在Spring Boot环境中是非常容易实现加密算法配置的,只需要创建一个Password Encoder对象即可。
 
注意:这里我们可以有多种创建PasswordEncoder对象的写法!并且别忘了把“/user/register”注册接口直接放行,注册接口不应该拦截。
 
BCryptPasswordEncoder加解密原理
 
我前面说过,BCrypt Password Encoder加密时,每次都会随机生成一个盐值混入到密码中,以此保证即使密码明文一样,最终得到的密文也不一样。但是这时候问题就来了,这个盐值是BCryptPasswordEncoder自动生成的,我们程序员也不知道,那到时候怎么进行密码的比对呢?因为比对密码时,肯定也需要把明文添加盐值后再加密才能比对啊!别急,往下看!
 
BCrypt Password Encoder调用 encode(..) 方法对密码明文加密时,每次都会随机的生成一个盐值,把这个盐值和明文再一起混淆最终得到密码的密文,所以这个最终的密文分为两部分:盐值和最终加密的结果。
 
BCryptPasswordEncoder调用matches(..)方法对比的时候,会利用自己特定的方法,先从密文里面拿出盐值,然后利用该盐值对密码的明文进行加密得到一个新的密文,最后利用这个新生成的密文和之前的密文进行对比,这样就能知道传递过来的密码是否和存储的密码是否一样了。
 
三. 利用其他Encoder进行加密实现
 
1. MessageDigestPasswordEncoder的用法
 
除了可以使用上面提到的默认的BCrypt Password Encoder加密方案之外,我们还可以使用Message Digest Password Encoder方案,该方案内部是采用"MD5"、"SHA-1"、"SHA-256"等信息摘要算法实现的加密,所以我们需要在构造的时候传入MD5等算法名称字符串。这个配置在SecurityConfig类中实现即可!
 
利用Message Digest Password Encoder 的encode(..) 加密方法,每次都会随机生成盐值,所以对相同的明文进行多次加密,每次得到的结果是不一样的。
 
Message Digest Password Encoder这个加密的最终结果也是分为两部分:盐值 + MD5 (password+盐值)。那么当我们调用 matches(..) 方法对比密码的时候,也是先从密文中得到盐值,然后利用该盐值再加密明文,最后利用这个新生成的密文和之前的密文进行对比。
 
2. DelegatingPasswordEncoder的用法
 
我们还有另一种加密实现写法,就是利用Delegating Password Encoder来进行实现。
 
Delegating Password Encoder是Spring Security 推出的一套兼容方案,该方案会根据加密类型的id字符串(idFor Encode),去自身缓存的所有加密方式中(idTo Password Encoder)取出对应的加密方案对象,然后对明文进行加密和密文的对比。
试听课
(责任编辑:代码如诗)
------分隔线----------------------------
栏目列表
推荐内容