【问题标题】:Spring Security >5.0.0 removed Md5PasswordEncoderSpring Security >5.0.0 移除了 Md5PasswordEncoder
【发布时间】:2018-09-12 23:48:55
【问题描述】:

我有一个使用 Spring 安全性的 Spring 项目。我使用的是 Spring Boot 1.5,现在我迁移到了 Spring Boot 2.0。

我注意到 Md5PasswordEncoder 在 Spring Security 的最终版本中已被删除。相反,Md4PasswordEncoder 仍然存在,即使已弃用 (https://docs.spring.io/spring-security/site/docs/5.0.3.RELEASE/api/)。

我应该使用外部 MD5 编码器还是将分类移动到其他地方?

【问题讨论】:

  • 你根本不应该使用MD5

标签: java spring spring-boot spring-security


【解决方案1】:

Md5PasswordEncoder 不复存在的事实并不意味着 Spring Security 5 无法创建 MD5 哈希值。它为此使用new MessageDigestPasswordEncoder("MD5")

有两个选项,都适用于新的DelegatingPasswordEncoder,它需要密码前缀来确定散列算法,例如{MD5}password_hash

要么将默认密码编码器设置为MD5(大写!),因此如果密码没有前缀,则应用默认编码器:

PasswordEncoder passwordEncoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
passwordEncoder.setDefaultPasswordEncoderForMatches(new MessageDigestPasswordEncoder("MD5"));

为数据库中现有的密码哈希添加前缀{MD5}。这样DelegatingPasswordEncoder 就代表了`MD5' 散列器。比如:

update myusertable set pwd = '{MD5}' || pwd;

【讨论】:

  • 你能指定 PasswordEncoderFactories 包含哪个包吗?
  • 应该是来自spring-security-coreorg.springframework.security.crypto.factory.PasswordEncoderFactories
【解决方案2】:

如果你想使用 MD5 你可以自定义:

@Bean
public PasswordEncoder passwordEncoder() {
    return new PasswordEncoder() {
        @Override
        public String encode(CharSequence charSequence) {
            return getMd5(charSequence.toString());
        }

        @Override
        public boolean matches(CharSequence charSequence, String s) {
            return getMd5(charSequence.toString()).equals(s);
        }
    };
}

public static String getMd5(String input) {
    try {
        // Static getInstance method is called with hashing SHA
        MessageDigest md = MessageDigest.getInstance("MD5");

        // digest() method called
        // to calculate message digest of an input
        // and return array of byte
        byte[] messageDigest = md.digest(input.getBytes());

        // Convert byte array into signum representation
        BigInteger no = new BigInteger(1, messageDigest);

        // Convert message digest into hex value
        String hashtext = no.toString(16);

        while (hashtext.length() < 32) {
            hashtext = "0" + hashtext;
        }

        return hashtext;
    }

    // For specifying wrong message digest algorithms
    catch (NoSuchAlgorithmException e) {
        System.out.println("Exception thrown"
                + " for incorrect algorithm: " + e);
        return null;
    }
}

【讨论】:

    【解决方案3】:

    您应该改用org.springframework.security.crypto.password.PasswordEncoderHere 是一篇关于切换到新界面的好文章。

    【讨论】:

    【解决方案4】:

    Spring 删除 MD5,因为它不再足够安全。你应该使用 Bcrypt。

    【讨论】:

    • 我需要使用 MD5,因为支付网关需要使用 MD5 对请求的某些部分进行哈希处理。这不是我的选择 ;-) 我将 Bcrypt 用于其他一切。
    【解决方案5】:

    我的解决方案如下:

    protected static String mergePasswordAndSalt(String password, Object salt, boolean strict) {
            if (password == null) {
                password = "";
            }
    
            if ((strict) && (salt != null) && ((salt.toString().lastIndexOf("{") != -1) || (salt.toString().lastIndexOf("}") != -1))) {
                throw new IllegalArgumentException("Cannot use { or } in salt.toString()");
            }
    
            if ((salt == null) || ("".equals(salt))) {
                return password;
            }
            return password + "{" + salt.toString() + "}";
        }
    
        public static String EncodingPassword(String password, String salt) {
            String merge = mergePasswordAndSalt(password,salt,false);
            return DigestUtils.md5Hex(merge);
        }
    

    用上面的函数替换下面的代码:

    new  Md5PasswordEncoder().encodePassword(String rawPass, Object salt);
    

    从spring-security-core-3.1.4.RELEASE.jar中的Md5PasswordEncoder源代码中可以看出它是如何处理密码和盐的:

      //org.springframework.security.authentication.encoding.BasePasswordEncoder.class
    
      protected String mergePasswordAndSalt(String password, Object salt, boolean strict)
      {
        if (password == null) {
          password = "";
        }
    
        if ((strict) && (salt != null) && (
          (salt.toString().lastIndexOf("{") != -1) || (salt.toString().lastIndexOf("}") != -1))) {
          throw new IllegalArgumentException("Cannot use { or } in salt.toString()");
        }
    
        if ((salt == null) || ("".equals(salt))) {
          return password;
        }
        return password + "{" + salt.toString() + "}";
      }
    

    【讨论】:

      猜你喜欢
      • 2014-03-04
      • 2013-08-31
      • 2017-05-30
      • 2018-02-19
      • 1970-01-01
      • 2021-11-12
      • 2015-02-26
      • 2019-02-01
      • 2020-11-10
      相关资源
      最近更新 更多