php - 清理用户密码

标签 php sql pdo hash

在对用户提供的密码进行哈希处理并将其存储到我的数据库之前,我应该如何转义或清除它们?

当 PHP 开发人员出于安全目的考虑对用户密码进行哈希处理时,他们通常倾向于将这些密码视为其他用户提供的数据。这个主题经常出现在与密码存储相关的 PHP 问题中;开发人员经常希望使用诸如 escape_string()(在各种迭代中)、htmlspecialchars()addslashes() 和其他人在对其进行散列并将其存储在数据库中之前。

最佳答案

您不应该对您将使用 PHP 的 password_hash() 散列的密码进行转义、修剪或使用任何其他清理机制。出于多种原因,其中最大的原因是对密码进行额外的清理需要不必要的额外代码。

您会争辩(并且您会在每篇接受用户数据在您的系统中使用的帖子中看到这一点)我们应该清理所有用户输入,并且您对于我们从用户那里接受的所有其他信息都是正确的.密码不一样。 散列密码不能提供任何 SQL 注入(inject)威胁,因为字符串在存储到数据库之前已转换为散列。

散列密码的行为是使密码安全地存储在数据库中的行为。散列函数不赋予任何字节特殊含义,因此出于安全原因不需要对其输入进行清理

如果您遵循允许用户使用 passwords / phrases 的口头禅他们渴望和你don't limit passwords , 允许任何长度、任意数量的空格和任何特殊字符散列将使密码/密码短语安全,无论密码中包含什么。截至目前,最常见的散列(默认) PASSWORD_BCRYPT ,将密码变成一个 60 字符宽的字符串,其中包含随机盐以及散列密码信息和成本(创建散列的算法成本):

PASSWORD_BCRYPT is used to create new password hashes using the CRYPT_BLOWFISH algorithm. This will always result in a hash using the "$2y$" crypt format, which is always 60 characters wide.

存储散列的空间需求会随着函数中添加不同的散列方法而发生变化,因此存储散列的列类型总是更好,例如VARCHAR(255)TEXT .

您可以使用完整的 SQL 查询作为您的密码,它会被散列,使其无法被 SQL 引擎执行,例如,

SELECT * FROM `users`;

可以散列到 $2y$10$1tOKcWUWBW5gBka04tGMO.BH7gs/qjAHZsC5wyG0zmI2C.KgaqU5G

让我们看看不同的清理方法如何影响密码 -

密码是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 &quot;dessert topping&quot; &amp; a &lt;floor wax&gt;!     " // double quotes, ampersand and braces have been changed
string(65) "I'm a &quot;dessert topping&quot; &amp; a &lt;floor wax&gt;!     " // 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

您必须先通过您选择的清理方法运行发布的密码,然后才能将其结果用于密码验证。这是一组不必要的步骤,不会使哈希变得更好。


使用低于 5.5 的 PHP 版本?您可以使用 password_hash() compatibility pack .

你真的不应该使用 MD5 password hashes .

关于php - 清理用户密码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36628418/

相关文章:

php - 关于 phpMyAdmin config.inc.php 文件的问题

php - 通过 pdo 多次绑定(bind)相同参数的更简洁方法是什么

mysql - 插入后 1 天自动删除行(MySQL)

php - Yosemite 上的 MAMP - 连接错误 : SQLSTATE[HY000] [2002] No such file or directory

java - 从android发送数据到mysql数据库

php - 从不同数据库获取用户信息

php - Pdo 使用查询内的变量进行更新

php - PDO 插入不会抛出错误或插入表单数据

sql - 有没有办法仅在存在最大值时从 SQL/Access 中的字段返回值?

sql - 重命名主键和外键的 VALUES