从Google App Engine迁移用户至Google OpenID

7
几个月前,我迁移了离开Google App Engine。但是,由于我的用户通过GAE上的user_id属性进行识别,因此仍然依赖它进行身份验证。
为此,我的(现在外部的)应用程序使用加密、签名和时间戳的登录请求将用户重定向到Google App Engine应用程序。然后,GAE应用程序使用GAE的“Users”服务执行登录。成功登录GAE后,用户再次使用加密、签名和时间戳的响应被重定向到我的外部应用程序。
可以在这里这里找到基本实现。正如您所看到的,这非常基础,并且依赖于导致性能不佳的重加密。
在这种情况下,我的外部应用程序(在本例中为Django应用程序)将user_id存储在用户表的密码字段中。除了user_id之外,我只从GAE获取电子邮件地址以存储用户名和电子邮件在Django中。
现在,我想删除对GAE服务的依赖性。首先想到的方法可能是发送电子邮件给每个用户,要求他设置新密码,然后使用Django执行自己的身份验证。
我更喜欢依赖于Google的OpenID服务的解决方案,以便对用户实际上没有任何区别。这也是首选,因为我需要将用户发送到Google以获取Google日历API的AuthSub令牌。
问题在于,我找不到一种方法来获取给定Google帐户的GAE user_id属性,而不使用GAE。OpenID和所有其他身份验证协议都使用不同的标识符。
现在的问题是:谷歌是否提供了我尚未看到的可用于此目的的API?是否有任何其他可能的解决方案或想法来迁移用户帐户?
提前感谢!
4个回答

2

最好的方法是向用户展示一个“迁移”中间页面,该页面将重定向到Google OpenID提供程序,并提示他们在那里登录。一旦他们在两个位置都登录,您可以匹配两个帐户,并允许他们在未来通过OpenID登录。


谢谢你的回答,但正如我在其他评论中指出的那样:我真的很想避免过渡阶段、迁移期或任何类似的事情。我也希望确保没有人被落下。(我知道你的解决方案很好,但其他人可能不这样认为。)我应该补充一点的是,尽管我将user_id存储在Django auth_user表的密码字段中,但user_id并没有加密或哈希。如果存在将它们转换为OpenID标识符或类似内容的API,我可以轻松迁移。 - mback2k
@mback2k,您正在寻找的内容不存在。App Engine用户API返回的用户ID是内部标识符;它没有任何外部对应项,也没有任何方法将其转换为外部标识符。 - Nick Johnson
据我所知,Google OpenID标识符每个应用程序只有一个,您无法生成新的标识符。如果您可以从用户ID映射到应用程序的OpenID ID,则作为App Engine应用程序所有者,您可以将用户的身份连接到多个站点。 - Nick Johnson
需要考虑两个问题:1. 没有变化,因为用户ID已经允许我在多个站点上连接用户身份,因为它对于所有GAE应用程序都是全局唯一的。2. 是的,Google OpenID标识符每个应用程序只有一个,我认为这是你描述的问题的解决方案,而不是问题的来源。记住,我从全局唯一标识符到每个应用程序的唯一标识符。 (除非您能够使所有Google帐户使用您的GAE应用程序之一,然后使用API进行暴力破解,否则不应该进行反向查找。但仍然,新令牌将是每个应用程序的唯一标识符。) - mback2k
1
如果存在这样的API,作为应用引擎应用程序所有者,您可以调用convert_userid(user,'domaina.com')convert_userid(user,'domainb.com')。现在您知道用户在两个不同站点上的OpenID,完全绕过了Google OpenID为每个站点发行不同URL的要点。 - Nick Johnson
显示剩余9条评论

1
据我所知,Google账户和Google OpenID之间唯一的共同标识符是电子邮件。
  1. 通过您当前的gae设置,在用户登录Google帐户时获取电子邮件。使用 User.email()。将此电子邮件与用户数据一起保存。

  2. 当您拥有大多数用户的电子邮件时,切换到Google OpenID。当用户登录时,获取电子邮件地址并在数据库中查找此用户。


感谢您的回复。问题在于用户可能已经在此期间更改了他的电子邮件地址,例如从非Gmail地址更改为Gmail地址或其他非Gmail地址。我以前遇到过这种情况,不得不手动提供一种方式让用户联系我并重新链接他们的旧帐户和相关数据。 user_id是一个静态标识符,永远不会更改,我真的很想确保没有人被落下。 - mback2k

1

为什么不尝试混合方法:

  1. 切换到OpenId
  2. 如果您的应用程序已经知道了userId,那么您就完成了
  3. 如果没有,请询问用户是否有要迁移的帐户
  4. 如果是,请使用旧机制登录并转移帐户
  5. 如果没有,请创建一个新帐户

0

谷歌具有唯一的标识符,它作为成功的OpenID认证请求的参数返回- *openid.claimed_id*。如果您切换到使用OpenID,您可以在用户使用新方法登录时第一次交换用户ID以获取此参数,而用户不会注意到其登录体验有任何不同之处。

认证过程的文档在这里概述。我建议使用混合OpenID+OAuth方法,以便您可以将请求令牌与特定ID关联起来,然后在返回时验证openid.claimed_id是否与您的原始请求令牌匹配。


谢谢。是的,但我如何将现有用户与他们的帐户匹配呢?关键是电子邮件地址或昵称不是唯一且静态的。近15%的用户使用非gmail / googlemail.com地址,这些地址可能随时更改。 我目前使用user_id作为用户识别的单一因素,但保留电子邮件和昵称以供信息和联系目的。 - mback2k
有两种可能的方法。第一种,您只需将他们在您的系统上的帐户与他们第一次登录的Google帐户关联起来。第二种(更安全)是在过渡期间,您首先使用当前方法对用户进行身份验证,然后再使用OpenID方法进行身份验证。 - Kevin P
还有一件事需要补充/澄清 - 在开始转换之前,您应该为用户生成自己的唯一标识符,并且不要依赖Google标识符来验证除OpenID认证之外的任何内容。 - Kevin P
其中一个不可靠,因为存在电子邮件标识符问题。人们在更改电子邮件地址时,意味着与我的服务上的数据的连接会丢失。目前,选项二可能是唯一的选择,尽管我更喜欢没有实际过渡期的解决方案。是的,当用户帐户成为真正的Django帐户时,它们将由用户名和/或电子邮件地址进行标识。OpenID只是为了方便而存在。再次感谢,但我仍然对其他想法感兴趣。 - mback2k

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接