1

有很多这样的问题所有这些都声称ClaimedIdentifier应该用来唯一地识别每个用户。

成功登录后,我存储ClaimedIndentifier在数据库中。每当用户登录时,我都会遍历我的记录以查找ClaimedIdentifier. 但是我注意到情况ClaimedIdentifiers正在发生变化。我应该在数据库中存储什么来识别我的用户。我正在使用Google帐户。这就是我检索将其存储到数据库中的方式

OpenIdRelyingParty rp = new OpenIdRelyingParty();
IAuthenticationResponse r = rp.GetResponse();
UserController.addUser(new UserController.User(r.ClaimedIdentifier.ToString(), 0));
4

1 回答 1

5

这不是 DotNetOpenAuth 独有的问题。这是谷歌的行为。Google 的 OpenID Provider 发布所谓的成对唯一标识符。只要您的 OpenID 领域是恒定的,它们对于给定用户将始终相同。

如果您在没有明确向 DotNetOpenAuth 的OpenIdRelyingParty.CreateRequest方法提供领域的情况下登录用户,DotNetOpenAuth 只会使用当前的 Web 应用程序根 URL。这是一个合理的默认值,但如果您的站点可以通过多种方式访问​​(例如 http 和 https,或者有和没有 www. 主机名),那么默认域将根据用户碰巧使用的 URL 而有所不同到达您的登录页面。当领域发生变化时,谷歌生成的声明标识符也会发生变化。

然后,解决方法是让您选择一个领域(如果可以的话,最好是带有 https 方案的领域)并将其显式提供给该CreateRequest方法。您还必须确保同一方法的 return_to 参数与您选择的领域共享一个公共根。例如,如果您选择的领域是: https ://www.mysite.com/ 那么您必须确保您的 return_to 基于此。像: https ://www.mysite.com/login.aspx

如果用户浏览到http://mysite.com/login.aspx,那将是 return_to 的默认 URL,它与您选择的领域不匹配。

所以总的来说,它可能看起来像这样:

var request = relyingParty.CreateRequest(
    "https://www.google.com/accounts/o8/id",
    "https://www.mysite.com/",
    new Uri("https://www.mysite.com/login.aspx"));

请注意,您的 return_to 不需要领域一样与每个请求完全相同。因此,您可以有多个登录页面 URL,并且每个都指定自己的 URL 作为 return_to 参数。但所有 return_to URL 都必须基于领域 URL。

随着该更改始终应用于您允许用户登录的所有位置,您应该会看到来自 google 的一致声明标识符。不幸的是,您已经使用其他领域获得的声明标识符将与您在此修复后获得的标识符不匹配。如果您需要合并这些用户帐户,并且如果您有用户的电子邮件地址,则可以尝试基于此进行合并。但是要非常小心这一步。只有当您确定存档的电子邮件地址属于这些用户时,才能安全地完成此操作。如果您在用户登录时通过 OpenID 获得了这些电子邮件地址,并仔细检查了它来自您信任的 OpenID 提供商并验证了电子邮件,那么您可能没问题。请注意,只需将 Google OP Identifier 硬编码CreateRequest保证只有 Google 用户登录。为了确保这一点,您必须在肯定断言出现时检查IAuthenticationResponse.Provider.Uri属性是否匹配https://www.google.com/accounts/o8/ud

于 2013-01-31T04:58:52.320 回答