为使用电子邮件和 facebook_id 的 Web 和移动设备创建用户创建/身份验证系统

Posted

技术标签:

【中文标题】为使用电子邮件和 facebook_id 的 Web 和移动设备创建用户创建/身份验证系统【英文标题】:Creating a user creation / auth system for web and mobile that uses both email and facebook_id 【发布时间】:2016-04-21 11:54:21 【问题描述】:

我正在使用 Ruby on Rails 为 ios 应用程序和 Web 应用程序(即可以从移动应用程序或 Web 前端创建用户)编写用户创建系统。我对使用像 Devise 这样的系统不感兴趣。

我已经有几年没有这样做了,所以只是想确保我的想法是最新的并且有意义。

步骤/假设

    我们将通过自定义 HTTP 字段(例如“X-auth_token”)管理服务器和客户端之间的状态。 它们可以通过电子邮件/密码凭证或通过 facebook 创建。

在邮件登录的情况下,用户只会发布以下json:


  user:
    email:'joe@test.com',
    password:'testpassword',
  

我将使用 Rails has_secure_password 对值进行哈希处理。

并且会返回


  user:
    id:23,
    auth_token:'md5value',
  

对于网络,我们将 auth_token 作为 cookie 值传递。对于 iOS 应用,auth_token 将作为自定义 HTTP 标头字段传递,例如“X-auth_token”

    在Facebook登录的情况下,他们将使用FacebookSDK,从FB获取范围权限,然后发布

user: is_facebook_login: true, fb_email: 'joe@test.com', fb_auth_token: 'abigvaluefromFB'

在服务器上,我们将确保他们通过以下方式传递有效的 fb_auth_token 凭据 用

调用 facebook
def self.verify_facebook fb_auth_token
  result = Net::HTTP.get(URI.parse("https://graph.facebook.com/me?access_token=#fb_auth_token"))
  obj=JSON.parse(result)
  obj["email"]
end 

并验证初始请求中发送的 fb_email 是否与 facebook 提供的电子邮件相对应。

以下是相应图表的步骤:

步骤

    对 facebook 的 oauth 请求,仅请求电子邮件 用户批准,电子邮件和身份验证令牌返回 发送 auth_token 到我们的服务器;如果是 facebook auth'd 客户端,请设置标志,以便只能通过 facebook 登录 通过 facebook 验证令牌是否准确

现在不担心,如果他们更改他们的 Facebook 电子邮件,那么运气不好。如果他们通过 Facebook 登录,然后想通过电子邮件/密码登录,那么运气不好。

在我们这一端,我们将生成一个 auth_token(一个 MD5 字符串),并将其发送回现在管理身份验证的客户端。从那时起,我们将发送一个自定义 HTTP 标头 X-auth_token

我们会回复


  user:
    id:23,
    auth_token:'md5value',
  

iOS 应用会通过https://github.com/kishikawakatsumi/KeychainAccess 将 auth_token 写入钥匙串

上述场景对于用户创建是否合理?

【问题讨论】:

您不会获得每个用户的电子邮件地址。他们可能不会授予您的应用权限,或者他们可能没有在 Facebook 存档的经过验证的电子邮件地址,例如如果他们使用自己的手机注册(这很可能是 iOS 用户的份额)。 谢谢@CBroe - 我会调查这个问题;我想这就是为什么这么多 iOS 应用程序即使在我通过 FB auth 提供电子邮件后仍要求电子邮件的原因。似乎是一种痛苦的 UI 体验。 【参考方案1】:

你描述的所有想法对我来说都是有效的,但整个描述看起来不完整。

缺少的部分是:

您如何存储和识别用户? 如何存储身份验证令牌? 一个用户可以拥有多个令牌吗? 是否要使旧令牌过期?

您已经有两个过程的描述 - 通过电子邮件注册新用户和通过 Facebook 注册新用户。

在服务器上我会这样存储它们,users 表:

ID - 整数,应用程序数据库中的唯一用户 ID email - 字符串,可选(对于 facebook,可以不存在),跨表唯一 facebook_id - 字符串,可选(通过电子邮件注册的用户将不存在),在表格中唯一 密码 - 字符串,可选(facebook 用户无密码)

而且我还会在这样的场景中合并电子邮件/脸书用户:

用户用邮箱注册,我们有ID和邮箱 用户注册/登录 facebook 并提供电子邮件 我们检查具有此类电子邮件的用户是否已存在并为其设置 facebook_id 现在用户可以使用 Facebook 或电子邮件登录

如果用户更改了他的 Facebook 电子邮件 - 这不会破坏任何内容,如果我们在 users 表中已经有了电子邮件,我们可以忽略此更改。所以用户仍然可以使用他的旧电子邮件登录。 (或者,使用额外的登录历史记录,我们可以检查用户从未使用电子邮件登录并将其替换为新用户)。

为 facebook 用户提供generate password 功能也很容易。他们可以在登录时输入电子邮件并生成密码,因此他们将来也可以使用电子邮件/密码登录。

您还可以添加forgot password 功能,该功能可以生成新密码并将其发送到用户的电子邮件 - 这可以由email 用户和提供电子邮件的facebook 使用。

如果我的想法正确,您希望有一个统一的方法来创建新用户和验证现有用户,如下所示:

用户输入,应用程序向后端发送电子邮件和密码 检查是否存在具有此类电子邮件的用户 用户存在 - 验证密码 通过 - 发送访问令牌 失败 - 发送错误 用户不存在 - 创建新用户和令牌 发送访问令牌

Facebook 类似,但我们检查 facebook_id 并通过对 facebook 的请求进行验证,而不是电子邮件/密码。

您还可以考虑使用单独的后端端点 - 一个用于注册新用户,另一个用于登录现有用户。 因为在上面的过程中,如果用户错误地输入了他的电子邮件,您将创建一个不期望的新用户。 对于 facebook 注册/登录可能不会有太大区别。

我认为允许一个用户拥有多个身份验证令牌从不同位置登录很有用,所以这里是 tokens 表:

ID - 整数、唯一 ID、主键 token - 字符串,唯一的访问令牌(您可以考虑将其设为主键) user_id - 整数,对拥有令牌的用户的引用 created_at - 日期时间,创建日期 expired - 布尔值,可用于实现令牌过期

常规请求如下所示:

有一个带有 X-auth_token 的请求 在数据库中查找令牌 找到合适的用户 允许用户访问他的资源

令牌过期可以这样完成:

有一个带有 X-auth_token 的请求 在数据库中查找令牌 检查是否now() - token.created_at > EXPIRATION_PERIOD 将令牌标记为已过期(token.expired = True + 保存) 返回错误“令牌已过期” 在下一次请求时 - 返回相同的错误,应用程序应要求用户再次登录

【讨论】:

谢谢-出发;让我看看明天;可能会保持赏金开放,但我可以提出一堆好的问题(有些已经解决;有些没有)。再次感谢 谢谢鲍里斯 - 正如你提到的,我留下了相当多的钱,但你涵盖了我们目前拥有的大部分内容(这是很好的验证)。【参考方案2】:

一些提示:

1) 请记住,facebook 电子邮件不是 facebook 用户登录电子邮件,而是个人资料电子邮件,如果用户将其留空,则默认为 username@facebook.com。这很重要,因为您可能希望用户通过电子邮件验证注册,在这种情况下我建议您使用模式要求用户在 fb 注册后输入他的电子邮件。

2) Facebook 用户没有密码,但他们可以使用“忘记我的密码”来更改密码,这种情况依赖于上面的用例(他们需要一个真实的电子邮件地址)。

3) 我不知道您的安全方案以及您正在创建的应用类型。但是您始终可以只使用 fb api 来检索用户数据并将其保存为默认用户。示例:从 fb api 获取数据并将用户保存为 token@facebook.com 密码:tokenWithMd5OrSomethingLikeThat userType: "facebook" 。当您开发一个不会很快更新的小型应用程序时,这很有用,更新速度更快。

【讨论】:

以上是关于为使用电子邮件和 facebook_id 的 Web 和移动设备创建用户创建/身份验证系统的主要内容,如果未能解决你的问题,请参考以下文章

微擎we7模块和模板安装方法

MongoDB索引,是不是可以同时创建普通和复合?

java:当字符串为We Are Happy.经过替换之后的字符串为We%20Are%20Happy

使用promise封装微信we.request进行数据请求

使用谷歌云的Eclipse we-app错误

企业实战-实现基于LNMP的电子商务网站