如何实现Security框架下兼容多种用户密码加密策略?

2026-05-20 23:562阅读0评论SEO基础
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计898个文字,预计阅读时间需要4分钟。

如何实现Security框架下兼容多种用户密码加密策略?

1. 说明:当已经上线的系统存在使用其他加密方式的加密数据,且密码不可逆,时,新的数据采用其他加密方式,且需要同时兼容多种加密方式的密码校验。

例如下列几种:- 密码学散列- 公钥加密- 同态加密- 软硬件安全模块(HSM)加密

一、说明

当已上线的系统存在使用其他的加密方式加密的密码数据,并且密码 不可逆 时,而新的数据采用了其他的加密方式,则需要同时兼容多种加密方式的密码校验。

例如下列几种情况:

  • 旧系统用户的密码采用了 MD5 的加密方式,而升级框架后的新系统则采用 BCrypt 的加密方式;
  • 当割接历史数据后会存在用户表中密码的 加密方式不统一 的问题,历史数据为 MD5 新数据为 BCrypt;
  • 所以需要系统支持同时兼容多种加密方式的密码校验。
  • 本文分享基于Security的PasswordEncoder来实现兼容多套用户密码加密方式。

     

    二、DelegatingPasswordEncoder

    在 spring Security 5.0之后,默认的密码加密方案其实是 DelegatingPasswordEncoder 它是一个代理类,而并非一种全新的密码加密方案,可以用来代理多种不同的密码加密方案。

      代码参考:

    Map<String, PasswordEncoder> encoders = new HashMap<>(); encoders.put("bcrypt", new BCryptPasswordEncoder()); encoders.put("ldap", new org.springframework.security.crypto.password.LdapShaPasswordEncoder()); encoders.put("MD4", new org.springframework.security.crypto.password.Md4PasswordEncoder()); encoders.put("MD5", new org.springframework.security.crypto.password.MessageDigestPasswordEncoder("MD5")); encoders.put("noop", org.springframework.security.crypto.password.NoOpPasswordEncoder.getInstance()); encoders.put("pbkdf2", new Pbkdf2PasswordEncoder()); encoders.put("scrypt", new SCryptPasswordEncoder()); encoders.put("SHA-1", new org.springframework.security.crypto.password.MessageDigestPasswordEncoder("SHA-1")); encoders.put("SHA-256", new org.springframework.security.crypto.password.MessageDigestPasswordEncoder("SHA-256")); encoders.put("sha256", new org.springframework.security.crypto.password.StandardPasswordEncoder()); encoders.put("argon2", new Argon2PasswordEncoder()); encoders.put("SM3", new SM3PasswordEncoder()); Assert.isTrue(encoders.containsKey(encodingId), encodingId + " is not found in idToPasswordEncoder"); DelegatingPasswordEncoder delegatingPasswordEncoder = new DelegatingPasswordEncoder(encodingId, encoders); delegatingPasswordEncoder.setDefaultPasswordEncoderForMatches(encoders.get(encodingId)); return delegatingPasswordEncoder;

    自动会根据数据的 encodingId 来使用对应的编译器处理密码

     

    三、如何使用

    3.1. 修改历史密码数据

    修改旧的密码数据的值,添加前缀标识 encodingId 格式如下:

    • 无盐值
    {encodingId}密码 例如源密码为:$2a$10$EgTOU7PMe.3jaMwFsumdweJcnY3TsTqyuJEdSaSKxdgwYchAwUJ1C 则修改为: {bcrypt}$2a$10$EgTOU7PMe.3jaMwFsumdweJcnY3TsTqyuJEdSaSKxdgwYchAwUJ1C
    • 有盐值
    {encodingId}{salt}密码 例如源密码为: 0758f7131c6c95c8e3df05e1ac50214c 则修改为: {MD5}{5Hstj}0758f7131c6c95c8e3df05e1ac50214c

    encodingId 的值可参考 PwdEncoderUtil 类

    如下图所示:

    3条记录中,前两条为原有的历史记录使用的是 MD5 的加密算法,然后新插入的数据使用的为 bcrypt 的加密算法,分别使用不同的前缀标识 encodingId

     

    3.2. 配置 PasswordEncoder 对象

    使用 DelegatingPasswordEncoder 类来定义 PasswordEncoder 并且指定默认加密方式为 bcrypt

    @Bean public PasswordEncoder passwordEncoder() { return PwdEncoderUtil.getDelegatingPasswordEncoder("bcrypt"); }

    以下两种情况下都是使用默认的加密方式:

    如何实现Security框架下兼容多种用户密码加密策略?

  • 使用 encode 方法加密数据。
  • 使用 matches 方法对比密文和原文时,密文没有 encodingId 标识。
  •  

    3.3. 参考代码

    gitee.com/zlt2000/microservices-platform/blob/master/zlt-commons/zlt-common-core/src/main/java/com/central/common/utils/PwdEncoderUtil.java

    本文共计898个文字,预计阅读时间需要4分钟。

    如何实现Security框架下兼容多种用户密码加密策略?

    1. 说明:当已经上线的系统存在使用其他加密方式的加密数据,且密码不可逆,时,新的数据采用其他加密方式,且需要同时兼容多种加密方式的密码校验。

    例如下列几种:- 密码学散列- 公钥加密- 同态加密- 软硬件安全模块(HSM)加密

    一、说明

    当已上线的系统存在使用其他的加密方式加密的密码数据,并且密码 不可逆 时,而新的数据采用了其他的加密方式,则需要同时兼容多种加密方式的密码校验。

    例如下列几种情况:

  • 旧系统用户的密码采用了 MD5 的加密方式,而升级框架后的新系统则采用 BCrypt 的加密方式;
  • 当割接历史数据后会存在用户表中密码的 加密方式不统一 的问题,历史数据为 MD5 新数据为 BCrypt;
  • 所以需要系统支持同时兼容多种加密方式的密码校验。
  • 本文分享基于Security的PasswordEncoder来实现兼容多套用户密码加密方式。

     

    二、DelegatingPasswordEncoder

    在 spring Security 5.0之后,默认的密码加密方案其实是 DelegatingPasswordEncoder 它是一个代理类,而并非一种全新的密码加密方案,可以用来代理多种不同的密码加密方案。

      代码参考:

    Map<String, PasswordEncoder> encoders = new HashMap<>(); encoders.put("bcrypt", new BCryptPasswordEncoder()); encoders.put("ldap", new org.springframework.security.crypto.password.LdapShaPasswordEncoder()); encoders.put("MD4", new org.springframework.security.crypto.password.Md4PasswordEncoder()); encoders.put("MD5", new org.springframework.security.crypto.password.MessageDigestPasswordEncoder("MD5")); encoders.put("noop", org.springframework.security.crypto.password.NoOpPasswordEncoder.getInstance()); encoders.put("pbkdf2", new Pbkdf2PasswordEncoder()); encoders.put("scrypt", new SCryptPasswordEncoder()); encoders.put("SHA-1", new org.springframework.security.crypto.password.MessageDigestPasswordEncoder("SHA-1")); encoders.put("SHA-256", new org.springframework.security.crypto.password.MessageDigestPasswordEncoder("SHA-256")); encoders.put("sha256", new org.springframework.security.crypto.password.StandardPasswordEncoder()); encoders.put("argon2", new Argon2PasswordEncoder()); encoders.put("SM3", new SM3PasswordEncoder()); Assert.isTrue(encoders.containsKey(encodingId), encodingId + " is not found in idToPasswordEncoder"); DelegatingPasswordEncoder delegatingPasswordEncoder = new DelegatingPasswordEncoder(encodingId, encoders); delegatingPasswordEncoder.setDefaultPasswordEncoderForMatches(encoders.get(encodingId)); return delegatingPasswordEncoder;

    自动会根据数据的 encodingId 来使用对应的编译器处理密码

     

    三、如何使用

    3.1. 修改历史密码数据

    修改旧的密码数据的值,添加前缀标识 encodingId 格式如下:

    • 无盐值
    {encodingId}密码 例如源密码为:$2a$10$EgTOU7PMe.3jaMwFsumdweJcnY3TsTqyuJEdSaSKxdgwYchAwUJ1C 则修改为: {bcrypt}$2a$10$EgTOU7PMe.3jaMwFsumdweJcnY3TsTqyuJEdSaSKxdgwYchAwUJ1C
    • 有盐值
    {encodingId}{salt}密码 例如源密码为: 0758f7131c6c95c8e3df05e1ac50214c 则修改为: {MD5}{5Hstj}0758f7131c6c95c8e3df05e1ac50214c

    encodingId 的值可参考 PwdEncoderUtil 类

    如下图所示:

    3条记录中,前两条为原有的历史记录使用的是 MD5 的加密算法,然后新插入的数据使用的为 bcrypt 的加密算法,分别使用不同的前缀标识 encodingId

     

    3.2. 配置 PasswordEncoder 对象

    使用 DelegatingPasswordEncoder 类来定义 PasswordEncoder 并且指定默认加密方式为 bcrypt

    @Bean public PasswordEncoder passwordEncoder() { return PwdEncoderUtil.getDelegatingPasswordEncoder("bcrypt"); }

    以下两种情况下都是使用默认的加密方式:

    如何实现Security框架下兼容多种用户密码加密策略?

  • 使用 encode 方法加密数据。
  • 使用 matches 方法对比密文和原文时,密文没有 encodingId 标识。
  •  

    3.3. 参考代码

    gitee.com/zlt2000/microservices-platform/blob/master/zlt-commons/zlt-common-core/src/main/java/com/central/common/utils/PwdEncoderUtil.java