我正在用Rails API构建一个简单的api,并希望确保我在这里正确的轨道。我正在使用设计来处理登录,并决定使用Devise的token_authenticatable
选项,该选项生成一个API密钥,您需要随每个请求一起发送。
我将API与骨干/牵线木偶前端配对,我一般想知道如何处理会话。我的第一个想法是将api密钥存储在本地存储或cookie中,并在页面加载时检索它,但是从安全的角度来看存储api密钥的方式让我感到困扰。通过查看本地存储/ cookie或嗅探任何经过的请求来获取api密钥并不容易,并使用它来无限期地冒充该用户?我目前正在每次登录时重置api密钥,但即使这样也很频繁 - 任何时候你登录任何设备,这意味着你会被其他人登录,这是一种痛苦。如果我可以放弃这种重置,我觉得从可用性的角度来看它会有所改善。
我可能在这里完全错了(并且希望我是),任何人都可以解释这种方式的认证是否可靠安全,如果不是,那么一个好的替代方案是什么?总的来说,我正在寻找一种方法,我可以安全地保持用户'登录'到API访问,而不经常强制重新认证。
token_authenticatable
易受时间攻击的影响,这在this blog post中得到了很好的解释。这些攻击是token_authenticatable
从Devise 3.1中删除的原因。有关更多信息,请参阅plataformatec blog post。
要拥有最安全的令牌认证机制,令牌:
如果你放弃其中一些支持可用性的观点,你最终会得到一种不那么安全的机制。就这么简单。如果您满足前三个要求并限制对数据库的访问,那么您应该足够安全。
扩展并解释我的答案:
secret_key_base
没有泄露,Cookies应该是安全的。SecureRandom.hex
只有你在Ruby 2.5+上。
宝石sysrandom
如果你是一个旧的Ruby。
为了解释为什么这是必要的,我建议阅读sysrandom
的自述文件和博客文章How to Generate Secure Random Numbers in Various Programming Languages。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查找程序找不到用户记录。这很容易受到定时攻击!您还应该有一个应急计划,例如,rake任务可以重置令牌子集或数据库中的每个令牌。
为了帮助您入门,您可以查看this gist(由Devise的作者之一)了解如何使用Devise实现令牌认证。最后,the Railscast on securing an API应该会有所帮助。
根据该项目的README,devise_token_auth gem的灵感来自StackOverflow的这篇帖子:https://github.com/lynndylanhurley/devise_token_auth
您可以尝试在您的API中使用rails4,它提供更高的安全性并使用设计3.1.0rc
TokenAuthenticatable
的弃用,但您可以为安全问题构建自己的TokenAuthenticatable
方法。它更可靠,更安全。对于令牌,会话存储,您可以通过http://ruby.railstutorial.org/chapters/sign-in-sign-out和http://blog.bigbinary.com/2013/03/19/cookies-on-rails.html更加明显。
最后你应该通过这些加密和解密“Unable to decrypt stored encrypted data”来获得更多的安全性。