security - MVC5 AntiForgeryToken 声明/"Sequence contains more than one element"

标签 security asp.net-mvc-5 antiforgerytoken claims

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

当我使用“本地”用户注册并登录时,一切都很好。 如果我用谷歌用户登录就可以了。 如果我使用设置为本地和外部登录的帐户登录,则会收到以下错误。

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

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

最佳答案

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

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 调用将引发您提到的错误。 作为解决方案,您可以使用其他声明,也可以在身份创建后更新它们,这取决于您的业务需求。

关于security - MVC5 AntiForgeryToken 声明/"Sequence contains more than one element",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20614954/

相关文章:

security - iFrame 注入(inject)攻击跟踪我们到新服务器

ruby-on-rails - Web 应用程序的安全性

javascript - HTML5 音频元素,源是音频,存储为数据库中的 varbinary 字节

c# - Hangfire 后台作业保持排队

asp.net - 可见的 GUID 是否存在安全风险?

oracle - 具有 EF6 运行时异常 'Member Mapping specified is not valid' 的 Entity Framework

linux - 我如何跨 linux 服务器处理 ValidateAntiForgeryToken

ruby-on-rails - 升级到 Rails 4.1 后跨域请求无效

asp.net-mvc - AntiForgeryToken是否需要在表单标签内

C Format-String漏洞,如何获取缓冲区中的地址