使用ASP.NETWebAPI,我的ExecutionContext不流入异步操作我很难理解ExecutionContext背后的机制。根据我在网上阅读的内容,安全(线程主体)、文化等上下文项目应该跨越正在执行的工作单元边界内的异步线程。我遇到了一个非常令人困惑且具有潜在危险的错误。我注意到我线程的CurrentPrincipal在异步执行中丢失了。下面是一个ASP.NETWebAPI场景的示例:首先,让我们设置一个简单的WebAPI配置,其中包含两个用于测试的委托处理程序。他们所做的就是写出调试信息并传递请求/响应,除了第一个“DummyHandler”,它设置线程的主体和要在上下文中共享的数据(请求的相关ID)。publicstaticclassWebApiConfig{publicstaticvoidRegister(HttpConfigurationconfig){config.MessageHandlers.Add(newDummyHandler());config.MessageHandlers.Add(newAnotherDummyHandler());config.Routes.MapHttpRoute(name:"DefaultApi",routeTemplate:"api/{controller}/{id}",defaults:new{id=RouteParameter.Optional});}}publicclassDummyHandler:DelegatingHandler{protectedoverrideTaskSendAsync(HttpRequestMessagerequest,CancellationTokencancellationToken){CallContext.LogicalSetData("rcid",request.GetCorrelationId());Thread.CurrentPrincipal=newClaimsPrincipal(newClaimsPrincipal(newClaimsIdentity(new[]{newClaim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name","dgdev")},"myauthisthebest")));Debug.WriteLine("虚拟处理程序线程:{0}",Thread.CurrentThread.ManagedThreadId);Debug.WriteLine("用户:{0}",(Object)Thread.CurrentPrincipal.Identity.Name);Debug.WriteLine("RCID:{0}",CallContext.LogicalGet数据(“rcid”));returnbase.SendAsync(request,cancellationToken).ContinueWith(task=>{Debug.WriteLine("DummyHandlerThread:{0}",Thread.CurrentThread.ManagedThreadId);Debug.WriteLine("User:{0}",(Object)Thread.CurrentPrincipal.Identity.Name);Debug.WriteLine("RCID:{0}",CallContext.LogicalGetData("rcid"));returntask.Result;});}}publicclassAnotherDummyHandler:MessageProcessingHandler{protectedoverrideHttpRequestMessageProcessRequest(HttpRequestMessagerequest,CancellationTokencancellationToken){Debug.WriteLine("AnotherDummyHandlerThread:{0}",Thread.CurrentThread.ManagedThreadId);Debug.WriteLine("用户:{0}",(Object)Thread.CurrentPrincipal.Identity.Name);Debug.WriteLine("RCID:{0}",CallContext.LogicalGetData("rcid"));退货申请;}protectedoverrideHttpResponseMessageProcessResponse(HttpResponseMessageresponse,CancellationTokencancellationToken){Debug.WriteLine("另一个虚拟处理程序线程:{0}",Thread.CurrentThread.ManagedThreadId);Debug.WriteLine("用户:{0}",(Object)Thread.CurrentPrincipal.Identity.Name);Debug.WriteLine("RCID:{0}",CallContext.LogicalGetData("rcid"));returnresponse;}}Easy接下来让我们添加一个ApiController来处理HTTPPOST,就像上传文件一样。publicclassUploadController:ApiController{publicasyncTaskPostFile(){Debug.WriteLine("Thread:{0}",Thread.CurrentThread.ManagedThreadId);Debug.WriteLine("用户:{0}",(Object)Thread.CurrentPrincipal.Identity.Name);Debug.WriteLine("RCID:{0}",CallContext.LogicalGetData("rcid"));如果(!Request.Content.IsMimeMultipartContent()){thrownewHttpResponseException(HttpStatusCode.UnsupportedMediaType);}try{awaitRequest.Content.ReadAsMultipartAsync(newMultipartFormDataStreamProvider(HttpRuntime.AppDomainAppPath+@"uploadtemp"));Debug.WriteLine("线程:{0}",Thread.CurrentThread.ManagedThreadId);Debug.WriteLine("用户:{0}",(Object)Thread.CurrentPrincipal.Identity.Name);Debug.WriteLine("RCID:{0}",CallContext.LogicalGetData("rcid"));返回新的HttpResponseMessage(HttpStatusCode.Created);}catch(Exceptione){returnRequest.CreateErrorResponse(HttpStatusCode.InternalServerError,e);}}}在使用Fiddler运行测试时,这是我收到的输出:Dummy处理程序线程:63用户:dgdevRCID:6d542847-4ceb-4511-85e5-d1b5bf3be476另一个虚拟处理程序线程:63用户:dgdevRCID:6d542847-4ceb-4511-85e5-d1b5bf3be476ThreadID:6463ddbfbe-14b7e5-455177用户:<<<主体在异步后丢失RCID:6d542847-4ceb-4511-85e5-d1b5bf3be476另一个虚拟处理程序线程:63用户:<<<主体仍然是46d5RCID-4511-85e5-d1b5bf3be476虚拟处理程序线程:65用户:dgdev<<<主体回来了?!?RCID:6d542847-4ceb-4511-85e5-d1b5bf3be476更令人困惑的是,当我将以下内容附加到异步行时:<<<<<<我现在收到此输出:虚拟处理程序线程:40用户:dgdevRCID:8d944500-cb52-4362-8537-dab405fa12a2另一个虚拟处理程序线程:40用户:dgdevRCID:8d944500-cb52-4362-8537-dab405fa12a2线程:65用户:dgdev<<<校长来了!RCID:8d944500-cb52-4362-8537-dab405fa12a2另一个虚拟处理程序线程:65用户:<<<主体丢失9RCID:cb52-4362-8537-dab405fa12a2虚拟处理程序线程:40用户:dgdevRCID:8d9445004-365-8537-dab405fa12a2这里的重点是async背后的代码调用了我的业务逻辑,或者只需要正确设置安全上下文。存在潜在的完整性问题。任何人都可以帮助解决发生的事情吗?提前致谢。我没有所有的答案,但我可以帮助填空和猜题。默认情况下,ASP.NETSynchronizationContext会流动,但它流动身份的方式有点奇怪。它实际上流式传输HttpContext.Current.User,然后将Thread.CurrentPrincipal设置为。因此,如果您只是设置Thread.CurrentPrincipal,您将看不到它正确流动。实际上,您将看到以下行为:将此应用于原始代码和输出:更新后的代码更改PostFile以在ASP.NET上下文之外运行其第二部分。所以它选择线程65,它恰好设置了CurrentPrincipal。由于它在ASP.NET上下文之外,因此不会清除CurrentPrincipal。因此,我认为ExecutionContext非常流畅。我确定Microsoft已经从wazoo中测试了ExecutionContext;否则,世界上的每个ASP.NET应用程序都会有一个严重的安全漏洞。需要注意的是,在这段代码中,Thread.CurrentPrincipal仅指当前用户的声明,并不代表实际的模拟。如果我的猜测是正确的,修复很简单:在SendAsync中,更改此行:Thread.CurrentPrincipal=newClaimsPrincipal(newClaimsPrincipal(newClaimsIdentity(new[]{newClaim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name","dgdev")},"myauthisthebest")));为此:以上是C#学习教程:使用ASP.NETWebAPI,我的ExecutionContext不流入异步操作如果分享的内容对你有用,需要进一步了解C#学习教程,希望你会多注意它——HttpContext.Current.User=newClaimsPrincipal(newClaimsPrincipal(newClaimsIdentity(new[]{newClaim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name","dgdev")},"myauthisthebest")));Thread.CurrentPrincipal=HttpContext.Current.User;本文来自网络收藏,不代表立场,如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处:
