我有两个使用devise进行身份验证的Rails应用程序:一个网站和一个API。即使我是这两个应用程序的所有者,出于多种原因,我希望两者完全分离。当用户在网站上注册时,会在API端自动创建一个帐户。我遇到的最大问题是让两个应用程序之间的用户表保持同步。我最终在网站用户模型上创建了一堆RESTful API回调,用于创建/更新API用户。
第二部分是代表登录网站的用户调用API。问题是我没有用户的解密密码,所以我可以进行API调用。所有API调用都使用基本HTTP身份验证。密码被散列到数据库中,无法解密(这是一件好事,谢谢你的设计)。因为我保持所有用户列在2个数据库之间同步,所以我的网站用户encrypted_password列与我的API用户encrypted_password列相同。
那么,我有什么选择来解决这个问题?我正在考虑修改API,以便每个常规调用的管理员调用采用管理员用户名和密码以及用户ID(例如,获取该用户的事务)。或者,在两个应用程序之间实现一个共享数据库 - 但我在用户和其他模型之间有很多关联......索引如何工作?!或者,劫持设计认证并将encrypted_password(从我的网站)与encrypted_password(到我的API)进行比较 - 因为它们完全相同;但这会打开一个安全的蠕虫病毒。或者,创建密钥身份验证并为用户生成唯一的GUID ......但是这将与存储在数据库中的解密密码一样糟糕。我讨厌所有这些解决方案。也许有人有更好的主意?
答案 0 :(得分:2)
当您在Devise中验证用户时,它会获取明文密码并将其与胡椒相结合并将其传递给bcrypt。如果加密的密码与数据库中的值匹配,则返回记录。
辣椒是基于你的rails app秘密。因此,除非两个应用具有完全相同的秘密,否则即使您拥有正确的加密密码,身份验证也会失败。请记住,bcrypt
的输入必须相同才能得到相同的结果。这意味着相同的明文,盐,胡椒和数量的延伸。
你是正确的,来回共享密码不是一个可靠的解决方案。您也是正确的,因为使用UUID而不是数字自动递增ID是解决方案的一部分。
您可以做的是实施您自己的身份验证提供程序。门卫gem可以很容易地设置您自己的OAuth提供程序(或者如果可以使用外部服务,您可以使用Auth0)。
Web应用程序将使用Devise + OmniAuth根据身份验证提供程序对用户进行身份验证,并使用返回的凭据来识别Web应用程序中的用户。
对于API应用程序,我会使用Knock进行JWT身份验证。 API服务器通过oauth gem代理您的身份验证服务器的位置。
但是,此时您应该考虑您的网络和API应用程序是否真的应该在不同的数据库上运行。保持两个数据库之间的同步写入可能是一项非常重要的任务,你应该问问自己在这个阶段是否真的需要它。
答案 1 :(得分:0)
JWT可以轻松地在JWT中包含用户ID等信息,而不依赖于外部持久性(如users表)。只需确保令牌已正确签名,并且不会在其中存储个人信息,例如电子邮件,因为通常JWT未加密但仅签名。
如果有兴趣的话,我实际上已经做了一个关于这个的写作教程。 https://www.moesif.com/blog/technical/restful-apis/Authorization-on-RESTful-APIs/