有很多问题,例如this和this,这些问题都声称ClaimedIdentifier
应该用于唯一标识每个用户。
成功登录后,我将ClaimedIndentifier
存储在数据库中。每当用户登录时,我遍历我的记录以查找ClaimedIdentifier
。但是我注意到ClaimedIdentifiers
正在发生变化。我应该在数据库中存储什么来识别我的用户。我使用的是Google
帐户。
这就是我检索将其存储到数据库中的方式
OpenIdRelyingParty rp = new OpenIdRelyingParty();
IAuthenticationResponse r = rp.GetResponse();
UserController.addUser(new UserController.User(r.ClaimedIdentifier.ToString(), 0));
答案 0 :(得分:5)
这不是DotNetOpenAuth独有的问题。这是Google的行为。 Google的OpenID提供商会发布所谓的成对唯一标识符。只要您的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的默认网址,与您选择的领域不匹配。
总而言之,它可能看起来像这样:
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都指定自己的URL作为return_to参数。但是所有的return_to网址都必须基于领域网址。
随着该更改始终适用于您允许用户登录的所有位置,您应该会看到来自Google的一致声明的标识符。遗憾的是,您使用其他领域获得的声称标识符与此修复后获得的标识符不匹配。如果您需要合并这些用户帐户,并且如果您有用户的电子邮件地址,则可以尝试基于此合并。但是非常警惕这一步。只有当您确定您拥有的电子邮件地址属于这些用户时,才能安全地完成此操作。如果您在用户登录时通过OpenID获取了这些电子邮件地址,并且双重检查它是来自您信任的OpenID提供商并验证电子邮件,那么您可能没问题。请注意,只需将Google OP标识符硬编码到CreateRequest
不即可确保只有Google用户才能登录。为了确保这一点,您必须检查IAuthenticationResponse.Provider.Uri
当肯定断言进来时,1}}属性匹配https://www.google.com/accounts/o8/ud
。