在散列用户提供的密码并将其存储在数据库中之前,我应该如何转义或清除这些密码?
当PHP开发人员考虑为安全目的散列用户密码时,他们往往倾向于想到这些密码,就像他们将提供任何其他用户提供的数据一样.这个主题经常出现在与密码存储相关的PHP问题中;开发人员通常希望在散列密码并将其存储在数据库中之前,使用诸如escape_string()
(在各种迭代中)、htmlspecialchars()
、addslashes()
等函数来清除密码.
在散列用户提供的密码并将其存储在数据库中之前,我应该如何转义或清除这些密码?
当PHP开发人员考虑为安全目的散列用户密码时,他们往往倾向于想到这些密码,就像他们将提供任何其他用户提供的数据一样.这个主题经常出现在与密码存储相关的PHP问题中;开发人员通常希望在散列密码并将其存储在数据库中之前,使用诸如escape_string()
(在各种迭代中)、htmlspecialchars()
、addslashes()
等函数来清除密码.
你永远不应该逃避、修剪或使用任何其他清除密码的机制,你将使用PHP的password_hash()
进行哈希运算,原因有很多,其中最大的一个原因是,对密码进行额外的清除需要不必要的额外代码.
你会争辩说(你在每一篇接受用户数据在你的系统中使用的帖子中都会看到),我们应该清理所有用户输入,而你对我们从用户那里接受的所有其他信息都是正确的.密码是不同的.Hashed passwords cannot offer any SQL injection threat because the string is turned into hash prior to storing in the database.
散列密码的行为是使密码安全地存储在数据库中的行为.哈希函数没有赋予任何字节特殊的含义,因此出于安全原因,不需要清除其输入
如果你遵循允许用户使用他们想要的passwords / phrases和don't limit passwords的咒语,允许任意长度、任意数量的空格和任何特殊字符哈希将使密码/密码短语安全,无论密码中包含什么.到目前为止,最常见的散列(默认值)PASSWORD_BCRYPT
将密码转换为一个60个字符宽的字符串,其中包含随机salt、散列密码信息和成本(创建散列的算法成本):
password_bcrypt用于使用crypt_blowfish算法创建新的密码散列.这将始终导致使用"$2y$"加密格式的散列,该格式始终为60个字符宽.
随着向函数添加不同的散列方法,存储散列的空间要求可能会发生变化,因此,存储的散列的列类型(如VARCHAR(255)
或TEXT
)越大越好.
您可以使用完整的SQL查询作为您的密码,它将被散列,使其无法由SQL引擎执行,例如,
SELECT * FROM `users`;
可以散列到$2y$10$1tOKcWUWBW5gBka04tGMO.BH7gs/qjAHZsC5wyG0zmI2C.KgaqU5G
Let's see how different sanitizing methods affect the password -个
密码为I'm a "dessert topping" & a <floor wax>!
(密码末尾有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 missing
string(65) "I'm a "dessert topping" & a <floor wax>! " // double quotes, ampersand and braces have been changed
string(65) "I'm a "dessert topping" & a <floor wax>! " // same here
string(48) "I\'m a \"dessert topping\" & a <floor wax>! " // escape characters have been added
string(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
在使用密码验证的结果之前,您必须通过您 Select 的清除方法运行发布的密码.这是一组不必要的步骤,并且不会使散列变得更好.
使用低于5.5的PHP版本?你可以使用password_hash()
-compatibility pack.
你真的不应该用MD5 password hashes.