0


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

PasswordEncoder

    PasswordEncoder是Spring Security框架默认使用的密码加密器,对应的数据表
sys_user

的密码

password

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

{noop}password

,否则就会抛出异常

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

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

Spring Security

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

PasswordEncoder

SpringBoot:注入BSryptPasswordEncoder实例

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

框架中提供的

BSryptPasswordEncoder

因此,只需要将

BSryptPasswordEncoder

对象注入到Spring容器中,

Spring Security

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

PasswordEncoder

对象,来进行密码校验。

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

配置类(

SpringSecurity

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

WebSecurityConfigureAdapter

)。示例代码如下,

package com.xwd.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

@Configuration
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
    //properties

    //methods

    /**
     * 注入Bean实例
     * @return BCryptPasswordEncoder实例
     */
    @Bean
    public PasswordEncoder getBCryptPasswordEncoder(){
        return new BCryptPasswordEncoder();
    }
}

BSryptPasswordEncoder详解

父接口

PasswordEncoder

   PasswordEncoder

Spring Security

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

Spring Security

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

/**
 * Service interface for encoding passwords.
 *
 * The preferred implementation is {@code BCryptPasswordEncoder}.
 *
 * @author Keith Donald
 */
public interface PasswordEncoder {
    ...
}
    其中,
Spring Security

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

BCryptPasswordEncoder

进行使用。

public interface PasswordEncoder {

    /**
     * Encode the raw password. Generally, a good encoding algorithm applies a SHA-1 or
     * greater hash combined with an 8-byte or greater randomly generated salt.
     */
    String encode(CharSequence rawPassword);

    /**
     * Verify the encoded password obtained from storage matches the submitted raw
     * password after it too is encoded. Returns true if the passwords match, false if
     * they do not. The stored password itself is never decoded.
     * @param rawPassword the raw password to encode and match
     * @param encodedPassword the encoded password from storage to compare with
     * @return true if the raw password, after encoding, matches the encoded password from
     * storage
     */
    boolean matches(CharSequence rawPassword, String encodedPassword);

    /**
     * Returns true if the encoded password should be encoded again for better security,
     * else false. The default implementation always returns false.
     * @param encodedPassword the encoded password to check
     * @return true if the encoded password should be encoded again for better security,
     * else false.
     */
    default boolean upgradeEncoding(String encodedPassword) {
        return false;
    }
}
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值标识是否进行了二次编码。

BSryptPasswordEncoder及其使用

成员方法
   BCryptPasswordEncoder

PasswordEncoder

的实现子类:使用了

BCrypt

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

$2a, $2b, $2y

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

   strength

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

    除了对
PasswordEncoder

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

getSalt()

**,

    private String getSalt() {
        if (this.random != null) {
            return BCrypt.gensalt(this.version.getVersion(), this.strength, this.random);
        }
        return BCrypt.gensalt(this.version.getVersion(), this.strength);
    }

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

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

SecurityUtils

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

    PS:可以看到,
BCryptPasswordEncoder类在使用时,主要还是调用**密码加密方法encode()**、**密码匹配/校验方法matchesPassword()**。
 /**
     * 生成BCryptPasswordEncoder密码
     *
     * @param password 密码
     * @return 加密字符串
     */
    public static String encryptPassword(String password)
    {
        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        return passwordEncoder.encode(password);
    }

    /**
     * 判断密码是否相同
     *
     * @param rawPassword 真实密码
     * @param encodedPassword 加密后字符
     * @return 结果
     */
    public static boolean matchesPassword(String rawPassword, String encodedPassword)
    {
        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        return passwordEncoder.matches(rawPassword, encodedPassword);
    }

测试代码


@SpringBootTest
@RunWith(SpringRunner.class)
public class SpringBoot_Demo_Test {
    //properties
    @Autowired
    @Qualifier(value = "BCryptPasswordEncoder") //Bean实例注入已经在本部分开头进行介绍
    private PasswordEncoder passwordEncoder;

    //methods

    @Test
    public void BCryptPasswordEncoder_test(){
        /**
         * 即使是相同的密码,BCryptPasswordEncoder每次的加密结果也是不同的
         * 原因在于:BCryptPasswordEncoder每次加密时都会使用一个随机的加密盐,产生不同的加密结果
         */
        String encode = passwordEncoder.encode("123456");//密码加密操作-将加密之后的结果存储到数据库中
        String encode1 = passwordEncoder.encode("123456");
        System.out.println(encode); // $2a$10$J0HqjTj2g98KceRapnRqW.Y4uQkPzGASFstgx1yba2JQG1muHj7L2
        System.out.println(encode1); //$2a$10$foxH4yrARWiaWwxyTXjFMOkSqkiOXsMaiQ6/oWbxxond5/BZqi1ke

        /**
         * 密码校验-虽然每次加密的结果不同,但是只要是由原来的密码加密过来的字符串,匹配时也都会返回true
         * 参数1:用户登录时输入的结果;参数2:正确的加密后的密码
         */
        boolean matches = passwordEncoder.matches("123456", "$2a$10$foxH4yrARWiaWwxyTXjFMOkSqkiOXsMaiQ6/oWbxxond5/BZqi1ke");
        System.out.println("检验结果:"+matches); //检验结果:true

    }
}


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

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

还没有评论