2016-09-14 28 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