清理用户密码,在对用户提供的密码进行散列并将其存储在数据库中之前,我应该如何避免或清除这些密码?

当 PHP 开发出于安全目的对用户密码进行哈希hashing 处理时,他们往往会像考虑其他用户提供的数据一样考虑这些密码。 这个主题经常出现在与密码存储有关的 PHP 问题中; 开发人员经常希望在散列密码并将其存储到数据库之前,使用 escape string ()(在各种迭代中)、 htmlspecialchars ()、 addslashes ()等函数来清理密码。

对于使用 PHP 密码散列()进行散列的密码,您绝不应该逃避、修改或使用任何其他清理机制,原因有很多,其中最大的一个原因是,对密码进行额外清理需要不必要的额外代码。
你会争辩(你会在每篇文章中看到用户数据被接受系统中使用) ,应该清理所有用户输入的信息,这样从用户那里接受的每一条信息都是正确的。 密码是不同的,散列密码不能提供任何 SQL ,因为字符串在存储到数据库之前被转换为散列。
散列密码就是使密码可以安全地存储在数据库中。散列函数没有赋予任何字节特殊的含义,因此出于安全原因,不需要清理
如果你遵循允许用户使用他们想要的密码,并且不限制密码的长度、空格和任何特殊字符,那么无论密码中包含什么,密码都是安全的。 到目前为止,最常见的散列(默认值) PASSWORD bcrypt 将密码转换成一个60个字符宽的字符串,其中包含一个随机 salt,以及散列密码信息和一个成本(创建散列的算法成本) :
Password bcrypt 用于使用 CRYPT blowfish 算法创建新的密码散列。 这总是会导致使用“ $2y $” crypt 格式的散列,该格式总是60个字符宽。
随着不同的散列方法被添加到函数中,存储散列的空间需求可能会发生变化,所以对于存储的散列,比如 VARCHAR (255)或 TEXT,最好使用更大的列类型。
You could use a complete SQL query as your password and it would be hashed, making it unexecutable by the SQL engine e.g.,
你可以使用一个完整的 SQL query 作为你的密码散列,例如,
SELECT * FROM users;
可以散列为 $2y$10$1tOKcWUWBW5gBka04tGMO.BH7gs/qjAHZsC5wyG0zmI2C.KgaqU5G
看看不同的清理方法如何影响 password
密码是 I'm a "dessert topping" & a ! (密码末尾有5个空格,这里不显示)
当我们应用以下方法时,我们会得到一些不同的结果:

var_dump(trim($_POST['upassword']));
var_dump(htmlentities($_POST['upassword']));
var_dump(htmlspecialchars($_POST['upassword']));
var_dump(addslashes($_POST['upassword']));
var_dump(strip_tags($_POST['upassword']));

结果

string(40) "I'm a "dessert topping" & a <floor wax>!" // spaces at the end are missingstring(65) "I'm a &quot;dessert topping&quot; &amp; a &lt;floor wax&gt;!     " // double quotes, ampersand and braces have been changedstring(65) "I'm a &quot;dessert topping&quot; &amp; a &lt;floor wax&gt;!     " // same herestring(48) "I\'m a \"dessert topping\" & a <floor wax>!     " // escape characters have been addedstring(34) "I'm a "dessert topping" & a !     " // looks like we have something missing

当我们将这些发送到 password hash ()时会发生什么?它们都会被散列化,就像上面的查询一样。 当您尝试验证密码时,问题就出现了。如果我们使用其中一个方法,我们必须在与 password verify ()进行比较之前重新使用它们。下面的方法行不通:
password_verify($_POST['upassword'], $hashed_password); // where $hashed_password comes from a database query
在使用密码验证的结果之前,必须通过选择的清理方法运行提交的密码。这不必要也不会优化散列。
使用5.5以下的 PHP 版本? 可以使用密码散列兼容包。

在散列密码之前,用规范化密码。 特别是:
附加映射规则: 任何非 ASCII 空间的实例必须映射到 ASCII 空间(u + 0020) ; 非 ASCII 空间是任何具有 Unicode 通用类别“ Zs”的 Unicode字符(u + 0020除外)
规范化规则: Unicode 规范化表单 c (NFC)必须应用于所有字符
This attempts to ensure that if the user types the same password but using a different input method, the password should still be accepted.
这是为了确保如果用户键入相同的密码,但用的是不同的输入方法,那么仍然应该接受这个密码