SimpleMembership 设置允许本地和多个 OAuth 登录都共享相同的UserProfile
- 因此单个用户可以使用本地密码或 FacebOogLiveWitter 登录。
(我应该声明,我在这个答案中假设 OAuth 提供者不会为本地帐户发回匹配的信息。如果他们这样做了,那么实际执行合并的原则是相同的,但是复杂性和步骤大大减少。)
如果用户使用现有用户名,OAuth 注册过程将拒绝用户,而不是尝试合并两个帐户。因此这并不简单,您必须自己构建功能。这个过程很复杂,因为用户可以从多个方向进行处理(因此您可以通过仅支持一两个来简化),并且您还需要加强安全性,以防有人试图合并到他们不拥有的帐户中.
我假设您对发布的链接感到满意,并且您已经遵循了 Facebook 帮助(例如)Facebook Login和The Login Flow for Web(无 JavaScript SDK),因此您有一个工作测试应用程序。
您的一般流程必须有多种用户旅程方法才能对用户有意义:
- 对于登录用户(使用本地帐户)
- 让他们登录 facebook 并关联帐户
- 让他们合并您网站上使用 facebook 登录的现有帐户
- 对于已登录的用户(使用 facebook 帐户)
- 让他们创建一个本地帐户
- 让他们合并您网站上的现有本地帐户
- 对于尝试注册本地帐户的未登录用户
- 让他们将此新帐户与已注册的 Facebook 登录名合并,并将其作为注册过程的一部分
- 对于尝试注册(或首次登录)Facebook 帐户的未登录用户
- 作为注册过程的一部分,让他们将其与现有的本地帐户相关联
等等
请求许可
(如果 OAuth 提供者发回了匹配的识别信息,例如电子邮件地址,您可以跳过此步骤)。
您应该强制执行确认安全,通常通过发送到合并目标帐户的电子邮件确认。否则:
- 有人可以第一次使用 facebook 登录您的网站
- 在此过程中,说他们“拥有”本地帐户的电子邮件地址或用户名(请记住,Facebook 不一定会确认他们的电子邮件是给你的)
- 因此可以访问现有的本地帐户
因此,一旦发出合并“请求”,您需要请求允许从合并的目标帐户继续进行。
MVC 4 帐户控制器
我将使用 Facebook 作为我们的 OAuth 示例。比较在本地身份验证框架与 OAuth 上注册用户时发生的情况:
- 本地:在 pages_Membership 中创建一个条目,并在 UserProfile 中创建一个具有相同 UserId 的条目(假设您正在使用 MVC 4 应用程序模板的默认表)
- OAuth:在 pages_OAuthMembership 中创建一个条目,在 UserProfile 中创建一个具有相同 UserId 的条目
现在让我们看看当用户第一次使用 Facebook 登录时会发生什么:
- 他们点击使用 Facebook 登录(或您的按钮显示的任何内容)
- 他们被带到 Facebook 登录
- 他们成功了(让我们假设,并忽略失败的情况)
- 然后他们被无形地发送给他们
/Account/ExternalLoginCallback
OAuthWebSecurity.SerializeProviderUserId
被调用,将 OAuth 详细信息传递给该操作
- 他们被重定向到
/Account/ExternalLoginConfirmation
并被要求为他们在您网站上的新存在提供用户名
- 如果该用户名可用,则创建 UserProfile 和 pages_OAuthMembership 条目
这个过程是您通过匹配一些独特的信息来“加入”帐户的机会。只要你UserId
在 UserProfile、webpages_Membership 和 pages_OAuthMembership 中得到相同的结果,你应该没问题。所以我们必须在/Account/ExternalLoginConfirmation
.
如果 OAuth 提供者发回了匹配的识别信息,例如电子邮件地址,这将变得很简单,在ExternalLoginConfirmation
操作中对此进行测试,并使用与下面概述的过程类似的过程进行自动合并。
但是,我认为您不能/不应该假设用户为您的网站和 OAuth 使用相同的电子邮件地址(出于多种原因,您也不应该这样做)。此外,可能在诸如 FacebOogLiveWitter 之类的条款和条件中,无论如何它都会阻止您询问他们帐户的电子邮件,如果他们目前不这样做,他们将来可能会这样做。
因此,您可以根据备选方案链接帐户,例如用户名或电子邮件地址或电话号码。无论哪种方式,您都需要他们输入一些针对帐户唯一的识别信息,并将撤回目标帐户。
包起来
所以把这一切放在一起:在这个答案的第一部分,我概述了你需要如何考虑多个用户旅程来合并帐户。我将使用示例 4.1。
您的流程将需要:
(假设 - 当用户首次使用本地帐户注册时,您要求他们提供电子邮件地址并验证它或假设它是有效的)
- 让用户第一次用facebook登录
- 问
Account/ExternalLoginConfirmation
他们是否愿意
- 与您创建一个新帐户
- 使用他们的 facebook 登录来访问现有帐户
- 假设是后者,那么您在一个新表(可能是“MergeAccountRequests”)中记录一个请求:
- facebook 帐户用户 ID
- 目标合并本地账号UserId
- 在您需要发送的电子邮件中使用的授权代码(从这一点开始,如果他们登录时没有确认合并,他们将不得不被发送到一个页面要求他们确认,而不是在其他数据库表中创建对象你以后要担心)
- 然后,您向目标合并(本地)帐户的地址发送一封电子邮件,请求获得完成合并的权限(标准确认电子邮件,带有链接)
- 当他们单击该链接或输入您发送给他们的代码时(您可以使用 SMS 和电子邮件),那么您需要合并两个帐户
- 选择“新”和“目标帐户”(在这种情况下,“新”是 Facebook 帐户,因为您还没有与之关联的数据)
- 删除“新”帐户的 UserProfile
- 将“新”账户 pages_OAuthMembership 表的 UserId 更改为与“目标”账户相同
- 将用户注销(因此,根据他们当前登录的帐户,不会出现复杂情况)
- 向用户显示一条消息,告诉他们合并几乎完成,他们现在可以使用任一帐户登录以确认并完成合并
我不会将他们发送到登录页面,而是在确认消息旁边为他们提供登录选项。