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

时间:2016-01-15 19:44:39

标签: ios facebook authentication

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

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

步骤/假设

  1. 我们将通过自定义HTTP字段(例如“X-auth_token”)管理我们的服务器和客户端之间的状态。
  2. 可以通过电子邮件/密码凭证或Facebook创建。
  3. 在电子邮件登录的情况下,用户将发布以下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”

    1. 在Facebook登录的情况下,他们将使用FacebookSDK,从FB获取作用域权限,并发布
    2. { 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提供的电子邮件相对应。

      以下是相应图表的步骤:

      STEPS

      1. oauth请求到facebook,仅请求发送电子邮件
      2. 用户批准,电子邮件和身份验证令牌返回
      3. 将auth_token发送到我们的服务器;如果facebook认证客户端,设置标志,以便只能通过Facebook登录
      4. 与facebook确认令牌是否准确
      5. 现在不担心,如果他们改变他们的Facebook电子邮件,运气不好。如果他们通过Facebook登录然后想通过电子邮件/密码登录,那就太难了。

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

        enter image description here

        我们将回复

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

        并且iOS应用会通过https://github.com/kishikawakatsumi/KeychainAccess

        将auth_token写入钥匙串

        上述方案对于用户创建是否合理?

2 个答案:

答案 0 :(得分:5)

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

缺少的部分是:

  • 如何存储和识别用户?
  • 如何存储身份验证令牌?
  • 一个用户可以拥有多个令牌吗?
  • 你想过期的旧令牌吗?

您已经有两个流程的说明 - 通过电子邮件进行新用户注册以及通过Facebook进行新用户注册。

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

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

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

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

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

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

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

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

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

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

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

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

  • ID - 整数,唯一ID,主键
  • token - string,唯一访问令牌(您可以考虑将其作为主键)
  • user_id - 整数,对用户的拥有,拥有令牌的人
  • created_at - 日期时间,创建日期
  • expired - boolean,可用于实现令牌过期

常规请求如下所示:

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

令牌过期可以这样完成:

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

答案 1 :(得分:3)

一些提示:

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

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

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