2012-02-08 90 views
4

我知道强制密码在用户创建它们一段时间后过期并不是Devise逻辑的一部分,我打算编写自己的代码来实现这一点。防止密码重复使用Devise

它也看起来像强迫用户不要重用最后一个X(在我的情况下10)密码将需要手动编码。

我的想法是,我会创建类似user_passwords表的东西,并在我的代码中使用逻辑来确保新密码与该用户的表中的任何内容不匹配。同时,我会将新密码插入表中,除非该用户已有10条记录,这意味着我会用新值覆盖最早的那条记录。表结构将是这样的:

user_passwords

  • USER_ID
  • encrypted_pa​​ssword
  • created_at

如果任何人有一个更好,更优雅的解决方案来处理这个问题,我感谢你。

+1

我认为“不要使用任何你最近的10个密码”是有些武断的,除非你有一个具体的商业原因。您可以轻松执行“不要使您的新密码与旧密码相同”。现实情况是,密码很难记住,而您将要驱动的行为是让用户在便签上记下密码。 – 2012-02-08 01:11:47

+0

这是客户的实际需求。这是一家金融公司。 – 2012-02-08 01:15:41

+0

然后,我不认为有比你提出的更优雅的解决方案... – 2012-02-08 01:19:17

回答

2

devise_security_extension似乎为我需要的。

但是,目前它不支持Devise 2.0或更高版本。我遇到了一些问题,必须将我的设计降级到1.5.3。根据他们留言板上的评论,他们目前正致力于将宝石移植到Devise 2.0兼容版本。

我已经为它的password_expirable和password_archivable模块给了它一个旋转。一切似乎都按预期工作。

它还支持secure_validatable,session_limitable和expired,前两种我可能会在不久的将来使用。

+0

我想覆盖session_limitable行为,因为我只需要http请求的行为。任何想法.. – Prem 2013-07-17 05:17:03

4

我知道强制密码在用户创建它们一段时间后过期并不是Devise逻辑的一部分,我打算编写自己的代码来实现这一点。

在实践中,安全相关的研究发现这是一个坏主意。那是因为你在每次变更时都会收益递减。也就是说,随着用户尝试遵守该策略,密码开始强劲并且随着时间的推移变弱。参见Peter Gutmann的Engineering Security和第7章,密码

从书中,其他愚蠢的东西包括复杂性要求。 (在您反对之前,请阅读本书的相关部分)。


...创造这样一个user_passwords表并使用逻辑在我的代码,以确保新密码不匹配任何在该表中为该用户。

而且一旦你阅读了这章,我将能够问:为什么你允许用户首先选择弱/受伤/破碎的密码?当Mark Brunett's list of 10 million leaked passwords结合:)


防止密码重用那些60个KB布隆过滤器看起来强大有用...

那将伤害的重用是跨站点密码重用。布朗,布拉肯,佐科利和道格拉斯在Generating and Remembering Passwords(应用认知心理学,第18卷,第6期,第641-651页)中指出,这些数字约为70%。 Das,Bonneau,Caesar,Borisov和Wang在​​报告了45%左右的数字。请注意,魔鬼网络研究必须破解密码,所以这个数字可能会更高,因为他们无法恢复所有的密码

为了使重复使用成为一个更严重的问题,用户必须记住约25个不同网站的密码Das,Bonneau,Caesar,Borisov和Wang在​​。

几年前,我甚至被烧伤了。我在两个低价值账户上使用了相同的密码。然后GNU's Savannah被黑客攻击,攻击者可以使用恢复的密码来破坏一个已用过的电子邮件帐户。

现在我只需要生成一个很长的随机字符串就可以了。我甚至不会为大多数网站写下它们。当我需要再次访问网站时,我只需要完成恢复过程。

+0

可悲的是密码恢复过程是穷人的双因素认证。 – zaph 2016-07-11 13:46:57

-1

devise_security_extension不导轨5为我工作,我创建了定制:

  • 创建迁移并添加一个额外的列,如: add_column:用户:old_passwords,:文本
  • 在模型中添加两​​个回调:after_save的:cache_old_pass和before_save:verify_old_pass

  • 创建回调的方法:

    private 
    def verify_old_pass 
        if self.encrypted_password_changed? 
        old_passwords.to_s.split(',').each do |pass_encrypted| 
         if Devise::Encryptor.compare(self.class, pass_encrypted, password) 
         errors.add(:base, 'Your password cannot be previous up to 3 back') 
         return throw(:abort) 
         end 
        end 
        end 
    end 
    
    def cache_old_pass # cache last 3 passwords 
    if self.encrypted_password_changed? 
        update_column(:old_passwords, ([self.encrypted_password] + old_passwords.to_s.split(',')[0, 3]).join(',')) 
    end 
    end 
    
+0

告诉我们您没有保存加密或不加密的实际密码,那完全是不负责任的。当攻击者获得数据库时,他也会得到加密密钥。 – zaph 2016-07-11 13:39:12

+0

这不是保存未加密的密码,它保存由设计生成的历史密码和由设计验证(没有被黑客入侵) – 2016-07-15 15:32:41

+0

所以我猜Devise :: Encryptor是错误的,因为它似乎执行散列,而不是加密 - 这是好消息。如果[docs](http://www.rubydoc.info/gems/devise/Devise/Encryptor#digest-class_method)解释到底发生了什么,但我猜你付出了什么,那将会很好。错误的命名应该受到惩罚,但是我们只是编码猴子,而不是专业人员。 – zaph 2016-07-15 15:50:33

0

Here是Devise gem的文档如何禁用以前使用的密码?