使用 Pwned Passwords API 在 Ruby 应用程序中设置更好的密码
在 Twilio,我们推崇使用第二重身份验证来保护用户账户,但这并不意味着我们忘记了第一重身份验证。鼓励用户选择强密码仍然是保护账户安全的第一道防线。
Troy Hunt 多年来一直在HaveIBeenPwned 网站上收集公开数据泄露事件的密码列表,如今他已开放了一个 API 来检查密码是否被使用过。本文将向您展示如何通过检查 pwned 密码 API 来鼓励用户使用更强的密码。
Pwned 密码 API
2017年,美国国家标准与技术研究院(NIST )在其数字身份指南中建议,应根据现有的公开数据泄露事件对用户密码进行检查。其理念是,如果密码之前曾出现在数据泄露事件中,则视为已被泄露,不应再使用。当然,该指南也建议使用双因素身份验证来保护用户帐户。
Pwned Passwords API允许您检查潜在密码是否已在网络上的一系列数据泄露事件中被泄露。该 API 有一个在线版本,您可以在其中输入密码并查看它是否曾被使用过。如果曾被使用过,它还会显示它出现的次数。该数据库中包含超过 5 亿个曾被使用过的唯一密码。
趁着这事儿,用你的邮箱地址去haveibeenpwned主服务看看你的凭证是否被泄露了。剧透一下,很可能已经泄露了!
API
Pwned Passwords API 允许我们根据密码数据库检查密码。根据检查结果,我们可以建议用户在注册服务、登录或更改密码时选择更安全的密码。
想到要把所有用户的密码发送给第三方,你的安全意识可能会有所担忧。不过还好,你不必担心。
您无需发送完整的密码,只需使用SHA- 1算法对密码进行哈希处理,并发送结果的前 5 个字符即可。这将返回数据集中所有以这 5 个字符开头的哈希值,如果哈希值的其余部分存在,则表示密码在列表中。您可以阅读本文,了解更多关于此技术、密码转储和 API 的信息。
让我们看一下如何在 Ruby 应用程序中使用这个功能,使用一些可以为您抽象该过程的 gem。
Ruby 中的密码
如果您想在任何 Ruby 应用程序中使用 Pwned 密码 API,那么我有一个很棒的库可以帮您。它叫做pwned,它能让您轻松通过 API 验证密码。
您可以在 GitHub 上查看pwned 的所有文档,但以下是如何入门。
安装宝石:
gem install pwned
打开 irb 会话来测试它。
irb -r pwned
> password = Pwned::Password.new("password")
> password.pwned?
#=> true
> password.pwned_count
#=> 3303003
好吧,怎么样?密码“password”在公开数据泄露事件中出现过超过300万次。😱
您还可以使用快捷方法:
> Pwned.pwned?("password1")
#=> true
> Pwned.pwned_count("password1")
#=> 2310111
哇!“password1”也一样糟糕!玩弄这样的数据确实很有趣,但如果你想在实际应用中使用它怎么办?你可以直接使用 gem,但如果你使用 Rails,那可就麻烦了。
破解密码和 Rails
我们之前在这篇博客中讨论过如何编写 ActiveModel 验证器。pwned gem 中自带了一个开箱即用的。如果你使用 Rails,可以通过将 gem 添加到你的 来使用此验证器Gemfile
:
gem "pwned", "~> 1.2.1"
运行 来安装 gem bundle install
。现在,你就可以在模型中访问:not_pwned
验证器了。例如:
class User < ApplicationRecord
has_secure_password
validates :password, not_pwned: true
end
现在,使用 Pwned Passwords API 验证用户对象非常简单:
user = User.new(email: "<a class="c1" href="mailto:philnash@twilio.com">philnash@twilio.com</a>", password: "password!")
user.valid?
#=> false
user.errors.messages
#=> {:password=>["has previously appeared in a data breach and should not be used"]}
让我们尝试一个强密码(但不是“正确的马电池钉” ——它在泄露的数据中出现了两次):
user.password = "wet koalas are terrifying"
user.valid?
#=> true
您还可以在验证器中使用其他选项,例如设置密码在数据中出现次数的阈值,或者设置 API 返回错误时的处理方式。详情请参阅文档。
如果您将 Rails 与Devise一起使用,则有一种更简单的方法来使用 API。
破解密码并设计
要使用 Devise 的 API,可以使用另一个 gem:devise-pwned_password。要使用它,请将 gem 添加到你的Gemfile
:
gem "devise-pwned_password", "~> 0.1.4"
运行bundle install
安装该 gem。现在你需要做的就是将:pwned_password
选项添加到模型的 devise 方法中User
:
class User < ApplicationRecord
devise :database_authenticatable,
:recoverable, :rememberable, :trackable, :validatable, :pwned_password
end
现在,当您的用户尝试注册时,Devise 将根据 Pwned Passwords API 进行检查。
您还可以使用 Devise 插件在现有用户登录时警告他们有关其密码的信息。要做到这一点,您需要after_sign_in_path_for(resource)
在您的 中覆盖ApplicationController
:
def after_sign_in_path_for(resource)
set_flash_message! :alert, :warn_pwned if resource.respond_to?(:pwned?) && resource.pwned?
super
end
高级选项
如果 API 在后台失败,Devise 插件和pwned gem都会将密码标记为有效。使用 pwned gem,您可以更改此网络故障行为。您可以将模型设置为无效,也可以运行您自己的程序来记录错误。
如果你不想因为密码只使用过一两次就将其标记为无效,这两个 gem 都提供了设置阈值的方法。使用 pwned 时,你可以在验证中设置阈值:
validates :password, not_pwned: { threshold: 1 }
使用 devise-pwned_password,打开config/initializers/devise.rb
并添加以下配置:
config.min_password_matches = 2
有关更多选项,请查看pwned和devise-pwned_password的文档。
更安全的密码,更安全的用户
使用Pwned Passwords API,您可以确保或鼓励您的用户在注册帐户、登录或更新密码时使用更好的密码。
正如我在开始时所说,我还建议在 Rails 应用程序中实施 2FA以确保用户帐户的安全。
您是否正在尝试其他方法来让用户使用更安全的密码?您认为 Pwned Passwords API 是一个不错的工具吗?请在评论区或 Twitter 上@philnash告诉我。
最后,在我编写 pwned gem 的初始版本时,我想特别感谢Dmytro Shteflyuk,他贡献了许多改进,包括 ActiveModel 验证器。谢谢!
使用 Pwned Passwords API 在 Ruby 应用程序中设置更好的密码最初于 2018 年 3 月 20 日在Twilio 博客上发布。
链接:https://dev.to/twilio/better-passwords-in-ruby-applications-with-the-pwned-passwords-api-4o9f