MVC5 AntiForgeryToken声明/"序列包含多个元素"

 夜-依晨_920 发布于 2023-02-10 10:14

案例:我有一个MVC5应用程序(基本上是带有脚手架视图的MVC5模板),启用了Google身份验证方法.该应用程序已经被配置成接受电子邮件作为用户名和存储来自谷歌分配了类似的姓,给定名称,电子邮件的NameIdentifier等方面的要求,对会员数据库(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}

使用仅限远程帐户或组合帐户登录时,claim-list如下所示

[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:     
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.
b__19() +321
System.Web.Mvc.Async.<>c__DisplayClass1e.
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.
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.
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.
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

Adi Bilauca.. 12

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

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对声明集合的调用将抛出你提到的错误.作为一种解决方案,您可以使用其他声明更新它们,在创建身份后,它可以满足您的业务需求.

1 个回答
  • 从以下方法(在创建用户标识时调用)可以看出,行为是正常的:

    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对声明集合的调用将抛出你提到的错误.作为一种解决方案,您可以使用其他声明更新它们,在创建身份后,它可以满足您的业务需求.

    2023-02-10 10:16 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有