devise的token_authenticatable安全吗?

我正在用Rails API构build一个简单的api,并且要确保我在这里的正确轨道上。 我使用devise来处理login,并决定去devise的token_authenticatable选项,它会生成一个API密钥,你需要发送每个请求。

我正在将API与骨干/木偶前端配对,并且通常想知道我应该如何处理会话。 我的第一个想法是将api密钥存储在本地存储或cookie中,并在页面加载时检索它,但是从安全angular度来看,存储api密钥的方式困扰了我。 通过查看本地存储/ cookie或嗅探任何经过的请求,并使用它无限地模拟该用户,将不容易抓住api密钥? 我目前正在重新设置每个login的api密钥,但即使这似乎很频繁 – 任何时候你login任何设备,这意味着你会登出每隔一个,这是一种痛苦。 如果我可以放弃这个重置,我觉得从可用性的angular度来看会有所改进。

我可能在这里完全错了(也希望是我),任何人都可以解释这种方式是否可靠地进行validation,如果不是一个好的select会是什么? 总体而言,我正在寻找一种方法,可以安全地保持用户loginAPI访问权限,而无需频繁强制重新授权。

token_authenticatable容易受到时间攻击,这在本博客文章中有很好的解释。 这些攻击是从Devise 3.1中删除token_authenticatable的原因。 请参阅plataformat博客文章了解更多信息。

要拥有最安全的令牌authentication机制,令牌:

  1. 必须通过HTTPS发送。

  2. 必须是随机的,密码强度。

  3. 必须安全地比较。

  4. 不得直接存储在数据库中。 只有令牌的散列可以存储在那里。 (请记住,令牌=密码。我们不在密码中以纯文本forms存储密码,对不对?)

  5. 应按照某种逻辑过期。

如果你放弃了一些有利于可用性的要点,那么最终会有一个机制不够安全。 就这么简单。 如果满足前三个要求并限制对数据库的访问,则应该足够安全。

扩展并解释我的答案:

  1. 使用HTTPS 。 这绝对是最重要的一点,因为它涉及嗅探器。

    如果你不使用HTTPS,那么很多可能会出错。 例如:

    • 为了安全地传输用户的凭证(用户名/电子邮件/密码),你将不得不使用摘要式身份validation,但是现在不能切断它,因为盐渍哈希可能被强制使用 。

    • 在Rails 3中,Cookie只被Base64编码笼罩,所以它们可以很容易地显示出来。 有关更多信息,请参阅解码Rails会话Cookie 。

      由于Rails 4,cookie存储是encryption的,所以数据既被数字validation,也不被攻击者读取。 只要您的secret_key_base不泄露,Cookies应该是安全的。

  2. 使用SecureRandom.hex生成令牌。 或者使用gem sysrandom

    显然SecureRandom不是那么安全。 不过,这里还有一个折衷:从标准库中挑选一些东西,或者挑选一些由某人维护的gem。 为了做出明智的决定,我build议阅读sysrandom的自述文件和博客文章如何以各种编程语言生成安全随机数 。

  3. 使用用户的ID,电子邮件或其他属性查找用户logging。 然后,用Devise.secure_compare(user.auth_token, params[:auth_token]将该用户的令牌与请求的令牌进行Devise.secure_compare(user.auth_token, params[:auth_token] 。如果您使用的是Rails 4.2.1+,则还可以使用ActiveSupport::SecurityUtils.secure_compare

    不要使用像User.find_by(auth_token: params[:auth_token])这样的Rails查找器来查找用户logging。 这很容易受到时间攻击!

  4. 如果每个用户要同时有几个应用程序/会话,则有两个选项:

    • 将未encryption的令牌存储在数据库中,以便可以在设备之间共享。 这是一个不好的做法,但我想你可以用UX的名义来做(如果你相信你的员工有数据库访问)。

    • 为每个用户存储尽可能多的encryption令牌,以允许当前会话。 所以如果你想在2个不同的设备上允许2个会话,在数据库中保存2个不同的令牌散列。 这个选项实现起来不那么简单,但它绝对安全。 它也有允许你提供给你的用户通过撤销令牌(就像GitHub和Facebook一样)在特定设备中结束当前活动会话的选项。

  5. 应该有某种机制导致令牌过期。 在实施这一机制时,要考虑到用户体验与安全性之间的平衡。

    如果Google没有使用六个月,Google会过期 。

    如果Facebook未使用两个月,Facebook会过期 :

    使用Facebook SDK的原生移动应用程序将获得长达60天的访问令牌。 当使用您的应用的用户向Facebook服务器发送请求时,这些令牌每天都会刷新一次。 如果没有请求,令牌将在大约60天后过期,并且该人员将不得不再次通过loginstream来获得新的令牌。

  6. 升级到Rails 4以使用其encryption的cookie存储。 如果你不能,那就自己encryptioncookie存储,就像这里build议的那样。 将身份validation令牌存储在encryption的cookie存储中绝对没有问题。

您还应该有一个应急计划,例如,重置令牌的子集或数据库中的每个令牌。

为了让你开始,你可以看看这个 (由Devise的作者之一)如何实现与Devise令牌authentication的要点 。 最后, 保证API的Railscast应该是有帮助的。

根据该项目的自述文件,devise_token_auth gem受这个StackOverflow文章的启发: https : //github.com/lynndylanhurley/devise_token_auth

您可以尝试使用您的API的rails4 ,它提供了更多的安全性,并使用devise3.1.0rc

对于令牌,会话存储,你可以通过http://ruby.railstutorial.org/chapters/sign-in-sign-out和http://blog.bigbinary.com/2013/03/19/cookies-on-rails .html更可爱。

最后你应该通过这种encryption和解密“ 无法解密存储的encryption数据 ”来获得更多的安全性。