13

案例:我有一个启用了 Google 身份验证方法的 MVC5 应用程序(基本上是带有脚手架视图的 MVC5 模板)。该应用程序已配置为接受电子邮件作为用户名,并将从 Google 分配的声明(例如姓氏、名字、电子邮件、名称标识符等)存储到会员数据库 (AspNetUserClaims)。

当我使用“本地”用户注册并登录时,一切都很好。如果我使用 Google 用户登录,那就没问题了。如果我使用设置为同时具有本地和外部登录的帐户登录,我会收到以下错误。

我尝试使用 Application_Start 中的 AntiForgeryConfig 选项将令牌的类型更改为不同的设置(示例)

AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.Email;

但是,当结合本地和外部登录时,似乎所有的声明都是重复的。最奇怪的是,声明集合(我假设有答案)对于组合登录和外部唯一登录是相同的。

当以本地用户身份登录时,这些声明被分配

[0]: {http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier: a71ff9c0-8dc4-478b-a6f1-2c4cc34b1e46}
[1]: {http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name: some@email.com}
[2]: {http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider: ASP.NET Identity}

当使用仅远程或组合帐户登录时,索赔列表如下所示

[0]: {http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier: 4ab33d77-c2a0-4eff-a759-5cca4323ecbf}
[1]: {http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name: some.other@email.com}
[2]: {http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider: ASP.NET Identity}
[3]: {http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier: https://www.google.com/accounts/o8/id?id=AitOGoogleIdentifierRemovedForPrivacygwgwgw}
[4]: {http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress: some.other@email.com}
[5]: {http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname: Other}
[6]: {http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname: Some}
[7]: {http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name: Some Other Person}

任何帮助都感激不尽!

错误和堆栈跟踪如下:

Server Error in '/' Application.

Sequence contains more than one matching element

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.InvalidOperationException: Sequence contains more than one matching element

Source Error:


Line 10: @using (Html.BeginForm())
Line 11: {
Line 12:     @Html.AntiForgeryToken()
Line 13:
Line 14:     <div class="form-horizontal">

Source File: x:\someweb\Views\someEntity\Create.cshtml    Line: 12

Stack Trace:


[InvalidOperationException: Sequence contains more than one matching element]
System.Linq.Enumerable.SingleOrDefault(IEnumerable`1 source, Func`2 predicate) +2533810
System.Web.Helpers.AntiXsrf.ClaimUidExtractor.GetUniqueIdentifierParameters(ClaimsIdentity claimsIdentity, String uniqueClaimTypeIdentifier) +701
System.Web.Helpers.AntiXsrf.ClaimUidExtractor.ExtractClaimUid(IIdentity identity) +186
System.Web.Helpers.AntiXsrf.TokenValidator.GenerateFormToken(HttpContextBase httpContext, IIdentity identity, AntiForgeryToken cookieToken) +242
System.Web.Helpers.AntiXsrf.AntiForgeryWorker.GetTokens(HttpContextBase httpContext, AntiForgeryToken oldCookieToken, AntiForgeryToken& newCookieToken, AntiForgeryToken& formToken) +174
System.Web.Helpers.AntiXsrf.AntiForgeryWorker.GetFormInputElement(HttpContextBase httpContext) +109
System.Web.Helpers.AntiForgery.GetHtml() +146
System.Web.Mvc.HtmlHelper.AntiForgeryToken() +39
ASP._Page_Views_Bruker_Create_cshtml.Execute() in x:\prosjekter\Laudi\TFS\Laudi\IWeb\Inspector\Inspector\Views\Bruker\Create.cshtml:12
System.Web.WebPages.WebPageBase.ExecutePageHierarchy() +271
System.Web.Mvc.WebViewPage.ExecutePageHierarchy() +120
System.Web.WebPages.StartPage.RunPage() +63
System.Web.WebPages.StartPage.ExecutePageHierarchy() +100
System.Web.WebPages.WebPageBase.ExecutePageHierarchy(WebPageContext pageContext, TextWriter writer, WebPageRenderingBase startPage) +131
System.Web.Mvc.RazorView.RenderView(ViewContext viewContext, TextWriter writer, Object instance) +695
System.Web.Mvc.BuildManagerCompiledView.Render(ViewContext viewContext, TextWriter writer) +382
System.Web.Mvc.ViewResultBase.ExecuteResult(ControllerContext context) +431
System.Web.Mvc.ControllerActionInvoker.InvokeActionResult(ControllerContext controllerContext, ActionResult actionResult) +39
System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive(IList`1 filters, Int32 filterIndex, ResultExecutingContext preContext, ControllerContext controllerContext, ActionResult actionResult) +116
System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive(IList`1 filters, Int32 filterIndex, ResultExecutingContext preContext, ControllerContext controllerContext, ActionResult actionResult) +529
System.Web.Mvc.ControllerActionInvoker.InvokeActionResultWithFilters(ControllerContext controllerContext, IList`1 filters, ActionResult actionResult) +106
System.Web.Mvc.Async.<>c__DisplayClass28.<begininvokeaction>
b__19() +321
System.Web.Mvc.Async.<>c__DisplayClass1e.<begininvokeaction>
b__1b(IAsyncResult asyncResult) +185
System.Web.Mvc.Async.WrappedAsyncResult`1.CallEndDelegate(IAsyncResult asyncResult) +42
System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +133
System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +56
System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeAction(IAsyncResult asyncResult) +40
System.Web.Mvc.Controller.<beginexecutecore>
b__1d(IAsyncResult asyncResult, ExecuteCoreState innerState) +34
System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +70
System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +139
System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +59
System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +40
System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult) +44
System.Web.Mvc.Controller.<beginexecute>
b__15(IAsyncResult asyncResult, Controller controller) +39
System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +62
System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +139
System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +59
System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +40
System.Web.Mvc.Controller.EndExecute(IAsyncResult asyncResult) +39
System.Web.Mvc.Controller.System.Web.Mvc.Async.IAsyncController.EndExecute(IAsyncResult asyncResult) +39
System.Web.Mvc.MvcHandler.<beginprocessrequest>
b__4(IAsyncResult asyncResult, ProcessRequestState innerState) +39
System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +70
System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +139
System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +59
System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +40
System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult) +40
System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result) +38
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +9688704
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +155
4

1 回答 1

13

从以下方法(创建用户身份时调用)可以看出,该行为是正常的:

await UserManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie)

SignInAsync方法。在执行中CreateIdentityAsync

...         
ClaimsIdentity claimsIdentity = new ClaimsIdentity(authenticationType, this.UserNameClaimType, this.RoleClaimType);
claimsIdentity.AddClaim(new Claim(this.UserIdClaimType, user.Id, "http://www.w3.org/2001/XMLSchema#string"));
claimsIdentity.AddClaim(new Claim(this.UserNameClaimType, user.UserName, "http://www.w3.org/2001/XMLSchema#string"));
claimsIdentity.AddClaim(new Claim("http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider", "ASP.NET Identity", "http://www.w3.org/2001/XMLSchema#string"));
if (manager.SupportsUserRole)
{
    foreach (string rolesAsync in await manager.GetRolesAsync(user.Id))
    {
        claimsIdentity.AddClaim(new Claim(this.RoleClaimType, rolesAsync, "http://www.w3.org/2001/XMLSchema#string"));
    }
}
if (manager.SupportsUserClaim)
{
    claimsIdentity.AddClaims(await manager.GetClaimsAsync(user.Id));
}
...

如您所见,默认情况下添加了三个声明。向他们添加您的“自定义”声明。这就是为什么您会重复声明的原因,这意味着SingleOrDefault对声明集合的调用将引发您提到的错误。作为一种解决方案,您可以使用其他声明或更新它们,在创建身份之后,这取决于您的业务需求。

于 2014-01-02T15:39:03.670 回答