验证密码有多严格?
How strict to verify passwords?
对于多用户站点,我应该多严格地验证我的用户密码?
我搜索了一下,只发现了关于如何验证用户密码的问题。但我知道 如何 为密码创建加盐哈希以存储在数据库中(PHP 的 password_hash()
),而且我知道 如何 验证这些密码 (PHP
s password_verify()
).
我想问我应该对我网站上的用户密码设置哪些类型的限制。因为密码从不显示在网页上,我是否应该像用户名一样对它们进行严格限制?
我知道显示了用户名,并且容易受到 XSS attacks 的攻击(我已经阻止了用户名),但是密码不同,并且不能通过这种方式被破解(我认为这是它是如何工作的;如果我错了请纠正我)。
我知道密码通常是个人的并且非常独特。我不知道是否应该限制可以使密码更安全的特殊字符,包括类似于 XSS 攻击中的特殊字符。
我在问是否应该允许任何密码(在特定字符限制内);如果不是,那么推荐的(安全)方法是什么?
第一,密码强度。
这对于防止密码猜测或暴力攻击很重要。密码越强——当然越好。例如,您可以将其限制为至少 10 个字符,并要求其中包含数字和大写字符。这已经很强大了,但您还可以要求使用 !
、$
、@
、#
等符号。该密码将非常安全。
至于安全地存储密码——这是一个不同的主题——你应该永远不要以开放的形式存储或显示密码。始终将它们散列为:
$password = password_hash($password, PASSWORD_DEFAULT);
并将生成的字符串存储在数据库中。
这在今天被认为是最安全的。
要检查输入的密码是否正确,您需要做的就是使用函数password_verify()
,将输入的密码与存储的散列密码进行比较。
$success = password_verify($entered_password, $hash_stored_in_mysql);
$success
将变为 true
或 false
,这就是您需要知道的密码是否匹配。
今天有这个 password_hash
和 password_verify
真是太好了,在添加这个有用的功能之前,人们使用了很多愚蠢和错误的方法来散列或加密密码!
您应该允许 ASCII 字符集中的任何字符(尽管 you could allow unicode 如果您想稍微复杂一些,例如在使用密码强度计时)。如果使用 bcrypt,您应该将最大长度设置为 72 个 ASCII 字符,因为 PHP 实现将散列仅限制为这些字符:
Using the PASSWORD_BCRYPT for the algo parameter, will result in the password parameter being truncated to a maximum length of 72 characters
这很好,因为某些实现对长度(55 个字符)施加了更大的限制。
With Unicode this is more complicated too,因为有些字符最多可能占用 4 个字节。我的建议:坚持使用 ASCII,密码足够安全(>= 64 位熵),因为它使事情变得更简单,如果您的用户使用密码管理器(他们应该使用),其中大多数只支持 ASCII 字符集。
XSS 只有在数据输出到页面时才会成为问题。理想情况下,您的系统应该实施一种策略,即只输入密码,从不输出(即使在 <input type="password" />
字段中)。这将增强密码的长期安全性。
对于多用户站点,我应该多严格地验证我的用户密码?
我搜索了一下,只发现了关于如何验证用户密码的问题。但我知道 如何 为密码创建加盐哈希以存储在数据库中(PHP 的 password_hash()
),而且我知道 如何 验证这些密码 (PHP
s password_verify()
).
我想问我应该对我网站上的用户密码设置哪些类型的限制。因为密码从不显示在网页上,我是否应该像用户名一样对它们进行严格限制?
我知道显示了用户名,并且容易受到 XSS attacks 的攻击(我已经阻止了用户名),但是密码不同,并且不能通过这种方式被破解(我认为这是它是如何工作的;如果我错了请纠正我)。
我知道密码通常是个人的并且非常独特。我不知道是否应该限制可以使密码更安全的特殊字符,包括类似于 XSS 攻击中的特殊字符。
我在问是否应该允许任何密码(在特定字符限制内);如果不是,那么推荐的(安全)方法是什么?
第一,密码强度。
这对于防止密码猜测或暴力攻击很重要。密码越强——当然越好。例如,您可以将其限制为至少 10 个字符,并要求其中包含数字和大写字符。这已经很强大了,但您还可以要求使用 !
、$
、@
、#
等符号。该密码将非常安全。
至于安全地存储密码——这是一个不同的主题——你应该永远不要以开放的形式存储或显示密码。始终将它们散列为:
$password = password_hash($password, PASSWORD_DEFAULT);
并将生成的字符串存储在数据库中。
这在今天被认为是最安全的。
要检查输入的密码是否正确,您需要做的就是使用函数password_verify()
,将输入的密码与存储的散列密码进行比较。
$success = password_verify($entered_password, $hash_stored_in_mysql);
$success
将变为 true
或 false
,这就是您需要知道的密码是否匹配。
今天有这个 password_hash
和 password_verify
真是太好了,在添加这个有用的功能之前,人们使用了很多愚蠢和错误的方法来散列或加密密码!
您应该允许 ASCII 字符集中的任何字符(尽管 you could allow unicode 如果您想稍微复杂一些,例如在使用密码强度计时)。如果使用 bcrypt,您应该将最大长度设置为 72 个 ASCII 字符,因为 PHP 实现将散列仅限制为这些字符:
Using the PASSWORD_BCRYPT for the algo parameter, will result in the password parameter being truncated to a maximum length of 72 characters
这很好,因为某些实现对长度(55 个字符)施加了更大的限制。
With Unicode this is more complicated too,因为有些字符最多可能占用 4 个字节。我的建议:坚持使用 ASCII,密码足够安全(>= 64 位熵),因为它使事情变得更简单,如果您的用户使用密码管理器(他们应该使用),其中大多数只支持 ASCII 字符集。
XSS 只有在数据输出到页面时才会成为问题。理想情况下,您的系统应该实施一种策略,即只输入密码,从不输出(即使在 <input type="password" />
字段中)。这将增强密码的长期安全性。