首页 > 解决方案 > 为什么 ``PasswordEncoder`` 实现在 Spring Security 5.x 中使用硬编码的 UTF-8 作为输入?

问题描述

我刚刚偶然发现了 Spring Security 5.x 的意外行为:提供的实现使用 UTF-8 编码以硬编码PasswordEncoder方式对数据进行散列(例如:MessageDigestPasswordEncoderBCrpyt)。因此,既没有办法注入另一种编码,也没有办法以任何方式配置这种行为。

现在我很想知道,为什么做出这个设计决定?(我毫不怀疑这是一个意义重大的决定;无论如何我们都在谈论 Spring!)

我在他们的官方参考资料中没有发现任何东西,他们也没有在他们的API 文档中说什么。老实说,我本来希望能找到更多关于这个设计决定的信息。如果不是作为理由,那么至少有一份关于这一事实的明确文件。(搜索当然有点困难,因为当涉及到处理散列的编码问题时,我们有语义冲突......也许我真的忽略了它?)

我最初的问题是,我必须处理一个遗留系统,其中密码哈希是使用ISO-8859-1 CP-1252编码作为哈希的基础创建的,因此我的 Spring Boot 2 应用程序中的匹配失败。当然,我可以通过更改遗留系统来解决这个问题——我很幸运,我不必维护遗留应用程序。

但我仍然想知道,为什么简单的解决方案(在 Spring a la 中为编码器定义适当的LATIN1编码spring.security.crypto.encoding=cp-1252)在这里不起作用。

这似乎与 Spring 的其余部分相反,您可以根据需要或想要配置几乎所有内容。这就是我在这里问这个问题的原因。

编辑:我刚刚了解到除了UTF-8之外的 MySQL也未能以正确的方式命名它们的LATIN1编码:CP-1252(或WINDOWS-1252,如果你愿意的话)。所以我对ISO-8859-1编码的假设是错误的。到底那个不影响问题本身!

标签: springspring-bootspring-securityutf-8character-encoding

解决方案


首先,我应该注意到投机性问题可能很难回答。尽管我经常参与 Spring Security 项目,但我在这里的想法并不是官方的,我邀请您对我的话持保留态度。

这个问题“为什么 X 开源项目还没有暴露 Y 的东西?” 基本上归结为几件事:

  • 编程实践很常见,以至于添加一个钩子来偏离它可能比对用户的帮助更令人困惑
  • 添加的任何钩子都是永久保持的钩子。弃用周期很长
  • 用户已经有了一个简单的替代方案
  • 暴露钩子会与代码中的类似位置不一致
  • 偏离编程实践是不安全/不好的实践等,因此维护人员希望确保它可以直接覆盖,但不一定只是开关翻转

将这些与事实相结合,这MessageDigestPasswordEncoder意味着@Deprecated添加的案例需要是一个强大的案例。

由于尚未提出强有力的案例,因此该功能不存在。MessageDigestPasswordEncoder对于不可配置的任何其他方面也是如此(例如最终编码的格式)。

取而代之的是,@jb-nizet 指出公开您自己的编码器(并使用密码编码器 API 迁移您的密码)非常简单。或者,如果这对您不起作用,请与团队记录一张票,我们会看看!


推荐阅读