0


Spring Security:PasswordEncoder密码加密匹配操作

PasswordEncoder

  1. PasswordEncoderSpring Security框架默认使用的密码加密器,对应的数据表
  1. sys_user

的密码

  1. password

字段需要以明文存储,并且要加上前缀

  1. {noop}password

,否则就会抛出异常

  1. java.lang.IllegalArgumentException: There is no PasswordEncoder mapped for the id "null"

(如下图所示),这样使用起来是极其不方便的,但是,

  1. Spring Security

也允许我们自己替换这个默认使用的

  1. PasswordEncoder

SpringBoot:注入BSryptPasswordEncoder实例

  1. 在实际开发中,我们一般使用
  1. spring security

框架中提供的

  1. BSryptPasswordEncoder

因此,只需要将

  1. BSryptPasswordEncoder

对象注入到Spring容器中,

  1. Spring Security

就会使用该对象替换掉默认使用的

  1. PasswordEncoder

对象,来进行密码校验。

  1. 所以,接下来的工作,就是定义一个
  1. SpringSecurityConfig

配置类(

  1. SpringSecurity

框架要求这个配置类需要继承

  1. WebSecurityConfigureAdapter

)。示例代码如下,

  1. package com.xwd.config;
  2. import org.springframework.context.annotation.Bean;
  3. import org.springframework.context.annotation.Configuration;
  4. import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
  5. import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
  6. import org.springframework.security.crypto.password.PasswordEncoder;
  7. @Configuration
  8. public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
  9. //properties
  10. //methods
  11. /**
  12. * 注入Bean实例
  13. * @return BCryptPasswordEncoder实例
  14. */
  15. @Bean
  16. public PasswordEncoder getBCryptPasswordEncoder(){
  17. return new BCryptPasswordEncoder();
  18. }
  19. }

BSryptPasswordEncoder详解

父接口

  1. PasswordEncoder

  1. PasswordEncoder

  1. Spring Security

框架默认使用的密码加密器。但是

  1. Spring Security

框架也提供了多个具体的实现子类(如上图所示)。

  1. /**
  2. * Service interface for encoding passwords.
  3. *
  4. * The preferred implementation is {@code BCryptPasswordEncoder}.
  5. *
  6. * @author Keith Donald
  7. */
  8. public interface PasswordEncoder {
  9. ...
  10. }
  1. 其中,
  1. Spring Security

框架源码中建议:在开发中,首选

  1. BCryptPasswordEncoder

进行使用。

  1. public interface PasswordEncoder {
  2. /**
  3. * Encode the raw password. Generally, a good encoding algorithm applies a SHA-1 or
  4. * greater hash combined with an 8-byte or greater randomly generated salt.
  5. */
  6. String encode(CharSequence rawPassword);
  7. /**
  8. * Verify the encoded password obtained from storage matches the submitted raw
  9. * password after it too is encoded. Returns true if the passwords match, false if
  10. * they do not. The stored password itself is never decoded.
  11. * @param rawPassword the raw password to encode and match
  12. * @param encodedPassword the encoded password from storage to compare with
  13. * @return true if the raw password, after encoding, matches the encoded password from
  14. * storage
  15. */
  16. boolean matches(CharSequence rawPassword, String encodedPassword);
  17. /**
  18. * Returns true if the encoded password should be encoded again for better security,
  19. * else false. The default implementation always returns false.
  20. * @param encodedPassword the encoded password to check
  21. * @return true if the encoded password should be encoded again for better security,
  22. * else false.
  23. */
  24. default boolean upgradeEncoding(String encodedPassword) {
  25. return false;
  26. }
  27. }
  1. PasswordEncoder

接口中只提供了3个待实现的抽象方法(源码如上),分别如下,

[1] String encode(CharSequence rawPassword);
密码加密:通常地,一个好的加密算法可以是SHA-1或者更大的hash与8字节、或者更大的随机生成盐的组合。

[2] **boolean matches(CharSequence rawPassword, String encodedPassword); **
其中:rawPassword对应用户提交的密码;encodedPassword对应正确密码编码后得到的字符串。
密码校验:校验密码编码后的字符串,与用户登录时提交的密码是否匹配,返回一个boolean布尔值表示是否校验通过。

[3] default boolean upgradeEncoding(String encodedPassword) {
return false;
}

如果为了更好的安全性,应当对一次编码后的密码进行二次编码,返回一个boolean值标识是否进行了二次编码。

  1. BSryptPasswordEncoder及其使用

  1. 成员方法
  1. BCryptPasswordEncoder

  1. PasswordEncoder

的实现子类:使用了

  1. BCrypt

强散列函数。客户端可以选择性的提供一个版本号(version,可选值:

  1. $2a, $2b, $2y

)和一个加密强度(strength,可选值:a.k.a. log rounds in BCrypt),以及一个SecureRandom实例。

  1. strength

加密强度默认值为10,值越大,安全性就越可靠。

  1. 除了对
  1. PasswordEncoder

接口提供的3个方法做了实现之外,也提供了用于获取加密盐的方法**

  1. getSalt()

**,

  1. private String getSalt() {
  2. if (this.random != null) {
  3. return BCrypt.gensalt(this.version.getVersion(), this.strength, this.random);
  4. }
  5. return BCrypt.gensalt(this.version.getVersion(), this.strength);
  6. }

  1. SecurityUtils安全服务工具类
  1. 在实际开发中使用时,面向
  1. 密码加密、密码匹配

两项操作,参考若依框架中:

  1. SecurityUtils

安全服务工具类的写法,摘录代码如下,

  1. PS:可以看到,
  1. BCryptPasswordEncoder类在使用时,主要还是调用**密码加密方法encode()**、**密码匹配/校验方法matchesPassword()**。
  1. /**
  2. * 生成BCryptPasswordEncoder密码
  3. *
  4. * @param password 密码
  5. * @return 加密字符串
  6. */
  7. public static String encryptPassword(String password)
  8. {
  9. BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
  10. return passwordEncoder.encode(password);
  11. }
  12. /**
  13. * 判断密码是否相同
  14. *
  15. * @param rawPassword 真实密码
  16. * @param encodedPassword 加密后字符
  17. * @return 结果
  18. */
  19. public static boolean matchesPassword(String rawPassword, String encodedPassword)
  20. {
  21. BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
  22. return passwordEncoder.matches(rawPassword, encodedPassword);
  23. }

测试代码

  1. @SpringBootTest
  2. @RunWith(SpringRunner.class)
  3. public class SpringBoot_Demo_Test {
  4. //properties
  5. @Autowired
  6. @Qualifier(value = "BCryptPasswordEncoder") //Bean实例注入已经在本部分开头进行介绍
  7. private PasswordEncoder passwordEncoder;
  8. //methods
  9. @Test
  10. public void BCryptPasswordEncoder_test(){
  11. /**
  12. * 即使是相同的密码,BCryptPasswordEncoder每次的加密结果也是不同的
  13. * 原因在于:BCryptPasswordEncoder每次加密时都会使用一个随机的加密盐,产生不同的加密结果
  14. */
  15. String encode = passwordEncoder.encode("123456");//密码加密操作-将加密之后的结果存储到数据库中
  16. String encode1 = passwordEncoder.encode("123456");
  17. System.out.println(encode); // $2a$10$J0HqjTj2g98KceRapnRqW.Y4uQkPzGASFstgx1yba2JQG1muHj7L2
  18. System.out.println(encode1); //$2a$10$foxH4yrARWiaWwxyTXjFMOkSqkiOXsMaiQ6/oWbxxond5/BZqi1ke
  19. /**
  20. * 密码校验-虽然每次加密的结果不同,但是只要是由原来的密码加密过来的字符串,匹配时也都会返回true
  21. * 参数1:用户登录时输入的结果;参数2:正确的加密后的密码
  22. */
  23. boolean matches = passwordEncoder.matches("123456", "$2a$10$foxH4yrARWiaWwxyTXjFMOkSqkiOXsMaiQ6/oWbxxond5/BZqi1ke");
  24. System.out.println("检验结果:"+matches); //检验结果:true
  25. }
  26. }


本文转载自: https://blog.csdn.net/weixin_43524214/article/details/128524170
版权归原作者 是席木木啊 所有, 如有侵权,请联系我们删除。

“Spring Security:PasswordEncoder密码加密匹配操作”的评论:

还没有评论