【问题标题】:Signed Global IDs for Authentication Tokens - secure or vulnerable?用于身份验证令牌的签名全局 ID - 安全还是易受攻击?
【发布时间】:2016-09-14 17:15:05
【问题描述】:

我发现 Signed Global IDs 对于重设密码帐户确认功能等基于令牌的东西非常棒,我很想听听关于它的安全性和可用性。

除了使用 Devise gem(模块 Confirmable + Recoverable)之外的常用方法是

A) 生成令牌(例如d3f64ce7c125410498b5393b33e7cf3c),将它们保存在数据库中并将链接发送到/account_confirmation/#token#

B) 将这些令牌的摘要保存在 DB 中并仅在邮件中发送令牌 - 而不是将它们与 BCrypt::Password.new(digest).is_password?(token) 进行比较。 Michael Hartl 在他的 Rails 教程中使用了这种更安全的方法。


C.但是签名全局 ID 呢?!

从 Rails 4.2 开始,Global ID Gem 包含在 Rails 中,主要用于 ActiveJobs。这就是我现在使用它们的方式,例如帐户确认资料:

在你的用户模型中包含GlobalID::Identification,而不是:

>> user_sgid = User.last.to_sgid(expires_in: 2.hours, for: 'confirmation')
=> #<SignedGlobalID:0x008fde45df8937

>> sgid_token = user_sgid.to_s
=> "BAhJIh5naWQ6Ly9pZGluYWlkaS9Vc2VyLzM5NTk5BjoGRVQ=--81d73[...]20e"

您可以通过电子邮件将此令牌与帐户确认链接发送给您的用户/account_confirmation/##sgid_token##

无需在数据库中保存account_confirmation_token 或它的摘要。此外,您无需保存 account_confirmation_sent_at 时间戳来检查链接是否仍然有效 - 所有内容都包含在 sgid_token 中:

>> GlobalID::Locator.locate_signed(sgid_token, for: 'confirmation')
=> #<User:0x007fae94bf6298 @id="1">
# use the User model to activate the account, login, and so on

# 2 hours later if link expired:
>> GlobalID::Locator.locate_signed(sgid_token, for: 'confirmation')
=> nil

您可以使用不同的令牌、不同的到期时间和用例发送多个链接。我喜欢这种方法。

更多信息在 github 上的 gem 描述中。


我的问题:

  • 签名全局 ID 令牌是否安全或容易受到特定攻击?
  • 不将令牌/摘要 + sent_at 保存到数据库有什么缺点吗?
  • sgid_tokens 最多有 200 多个字符,所以链接会变得很长,有什么问题吗?
  • 为什么不使用签名全局 ID 而是使用令牌/摘要的其他原因?

【问题讨论】:

    标签: ruby-on-rails ruby security devise token


    【解决方案1】:

    签名全局 ID 令牌是否安全或容易受到特定攻击?

    签名的全局 ID 似乎使用MessageVerifier

    MessageVerifier 使用 SHA1 哈希算法创建 HMAC 签名

    HMAC over SHA1 is still considered secure.

    不将令牌/摘要 + sent_at 保存到数据库的任何缺点?

    通常的主要缺点是您无法在服务器端撤销这些。例如,如果用户注销或您希望使特定用户的所有会话过期。

    还要确保在每个全局 ID 中保存了一些上下文。也就是说,忘记密码的用户签名 ID 不应该用于身份验证令牌。

    sgid_tokens 最多有 200 多个字符,所以链接会变得很长,任何 有这方面的问题吗?

    不是特别是,不是。

    不使用签名全局 ID 的其他原因 令牌/摘要?

    主要是您看不到它们或如上所述在服务器端撤销它们的事实。您还应该确保您使用的是强密钥(>= 128 位)并且此密钥保持私有。任何密钥泄露都会危及所有令牌,并允许攻击者生成自己的令牌。

    【讨论】:

    • 非常感谢您对此的意见!是的,您绝对正确地使用带有“for:'...'”选项的每个 GlobalID 的上下文,例如我在account_confirmationreset_password 之间有所不同。在数据库中存储摘要(而不是令牌)时,也无法“看到”令牌 - 但您关于撤销的观点是一个很好的观点......因此我使用expire_in 来确保链接 a 无效很长 - 但不可能完全撤销。
    猜你喜欢
    • 2013-02-12
    • 1970-01-01
    • 2012-07-06
    • 2011-06-08
    • 2019-08-30
    • 2016-12-18
    • 2017-03-21
    • 1970-01-01
    • 2017-04-27
    相关资源
    最近更新 更多