存储 oauth 和本地身份验证方法的最佳实践?
Posted
技术标签:
【中文标题】存储 oauth 和本地身份验证方法的最佳实践?【英文标题】:best practice for storing oauth AND local authentication methods? 【发布时间】:2011-09-21 11:19:16 【问题描述】:如果我要运行允许用户通过“本地”用户名/密码组合以及任意数量的 OAuth 服务进行身份验证的服务 - 用户数据模型会是什么样子?
通常,如果我自己处理所有登录,在“用户”数据库(假设 mysql)中,用户名和密码字段将被要求为非空。但是,如果我的用户只是想使用 Facebook 登录,我只需存储 Facebook 自动令牌,并且在本地没有任何用户名/密码。
此外,如果他们想使用 Twitter 凭据登录,然后使用 tumblr 登录,然后使用任何日常服务怎么办?我可以为每种类型保留一个字段,但这可能有点笨拙。由于缺少更好的术语,我最好保留另一个“身份验证方法”表,这样我就可以在用户之间建立一对多的关系以及如何对他们进行身份验证?
基本上,我想问是否有人知道这种情况下的行业标准最佳实践,或者可以为我指出正确的方向(或者是否有人实施了适合他们的类似方法)。一个用户,多种身份验证方法 - 保存该信息的最佳方式是什么?
如果我所做的任何假设是无效的,我很抱歉,请纠正我。
【问题讨论】:
就我个人而言,我不想处理超过一两个身份验证方案 - 尝试接受任何和一切都将成为一场噩梦。如果您的应用程序与 FB 的关系更密切,则允许使用 FB 等。话虽这么说......只谈论 OAuth + 本地,我认为您会在您的用户类上实现一个方法,比如 oauthenticated? (我是一个红宝石人),这会告诉你他们最初是本地认证的还是 o 认证的。然后在您的身份验证代码中,您需要根据他们用来让他们登录的方法进行检查和分支。之后,它应该没关系。 【参考方案1】:我不知道我的解决方案是否接近任何行业标准,但我之前已经在几个应用程序中做到了这一点。
您的应用程序中的身份应该从身份验证源中抽象出来。 我最终设置的是这样的:
User table:
id int
username varchar
email varchar
password varchar
Authentication profile table:
user_id int
service enum('website','google','facebook')
token varchar
[为了进一步规范化,使用服务元字段使服务成为自己的表。 ]
然后您的身份验证脚本会执行以下操作:
-
查找用户名/电子邮件
识别已知的身份验证配置文件
查看输入是否验证任何已知的身份验证配置文件和身份验证,或返回无效凭据
在某些服务的情况下,您需要自动生成一些用户字段值,或者在第一次身份验证期间提示用户输入,具体取决于您可以从服务中获得的数据类型。
【讨论】:
这与我希望的样子相似。用户表中也可能有一个 default_profile,因此人们只需点击 /login 即可知道该做什么,或者需要一个参数来指定要执行的登录类型。那么 auth_type = facebook 不需要其他任何东西,我只使用存储的令牌,但 auth_type = website 需要登录名和密码。听起来可行吗? (什么...... cmets 中没有换行符?) 是的,或者在 facebook 的情况下,您只需轮询 FB.Auth 事件并在用户到达页面时自动登录。 当用户重新登录时,应用如何知道此人之前是否登录过?基本上我不明白在我使用facebook登录一次之后如何确定id整数,然后使用Google第二次登录。我的应用会考虑这两个不同的用户吗?还是一个用户?重申一下,应用程序如何知道这两个登录名是同一个人(除了任何类型的 cookie)。 只是一个建议,在 OpenID Connect 中允许用户登录的实体被称为 Providers(OPs - OpenID Connect Providers),而想要请求用户登录的实体在 Providers 上,即 *** 、Spotify、Netflix 被称为服务。以良好命名法的名义,我建议对您的示例进行更新,即在“身份验证配置文件表:”部分中,通过 provider 更改 service。【参考方案2】:我认为您想要的是本地身份验证系统(可能是出于遗留原因?)以及支持使用委托身份验证登录的用户。委托认证的标准是OpenID。您可能想查看OpenID consumer libraries and samples,它应该让您了解存储 OpenID 凭据。不幸的是,Facebook 和 Twitter 不支持 OpenID,但流程几乎相同,即您的数据模型不会改变。我们已经实现了一个 OpenID 消费者来支持基于 OpenID 的登录和注册。为了支持本地身份验证,我们使用了 OpenID 提供程序。换句话说,我们既是消费者又是提供者。这样,即使是本地身份验证系统也是基于标准的。现在回答您关于架构的问题 - 我们将来源(本地、推特、脸书、谷歌、雅虎、美国在线)和电子邮件作为复合密钥,以及身份验证表中的令牌和/或密码。我们允许用户更改他们的显示名称,并拥有一个唯一的虚 URL,这也是该架构的一部分。用户在通过 OpenID 进入时可以选择设置密码,因为对于移动设备,他们需要密码(移动设备上没有很多 OpenID 支持)。 OAuth 解决了一个稍微不同的用例,在这种用例中,您处理授权而不是身份验证。这有帮助吗?如果您有任何问题,请随时发表评论,我很乐意提供更多详细信息 - 我只是不想在这一点上让您混淆太多信息。
【讨论】:
是的,整个 oauth 与 openid 的事情一直很混乱。如果你去facebook的认证页面,它没有提到openid,只是oauth。所以……必须同时支持? (假设我需要支持 facebook) OAuth 可以用作 OpenID 的子集,因为您混合了身份提供者和资源提供者。我可以告诉你我们在做什么——我们与其他 OpenID 提供商分开处理 facebook 和 Twitter,但不使用 OAuth,即我们没有为用户访问任何资源。在这种情况下,OAuth 或多或少用作身份断言机制,而不是资源访问。以上是关于存储 oauth 和本地身份验证方法的最佳实践?的主要内容,如果未能解决你的问题,请参考以下文章
为同一 API 混合多个身份验证模型是最佳实践吗? [关闭]