2016-09-14 67 views
1

我发现签名全局ID是真棒基于令牌的东西一样重置密码帐户确认功能,很想得到关于它的安全性和可用性的意见。除了使用设计的宝石验证令牌的签名全局ID - 安全还是易受攻击?

常用方式(模块可证实+可恢复)是

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

B)的节能摘要这些令牌在数据库中,只发送邮件中的令牌 - 比较它们与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,但因此令牌/摘要的其他原因?

回答

1

是签名的全局ID令牌安全还是易受攻击?

的签名全局ID似乎使用MessageVerifier

MessageVerifier创建使用SHA1哈希算法

HMAC over SHA1 is still considered secure HMAC签名。

没有将令牌/摘要+ sent_at保存到数据库中的缺点?

一般的主要缺点是你没有办法吊销这些服务器端。例如,如果用户注销或者您希望过期某个特定用户的所有会话。

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

sgid_tokens起来达到200多个字符,所以链接变得很长,有关于此问题的任何 问题?

不特别没有。

其他原因为什么不使用签名全局ID,但因此 令牌/摘要?

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

+0

非常感谢您对此的看法!而且,对于每个GlobalID使用“for:'...'”选项来使用上下文是完全正确的,例如,我在'account_confirmation'和'reset_password'之间有所不同。当在数据库中存储摘要(而不是令牌)时,也不可能“查看”令牌 - 但是关于撤消的观点是一个好的观点......因此,我使用'expire_in'来确保链接a无效长 - 但完全撤销是不可能的。 – Steffen