[英]How to get Windows Authenticated user in C# Web API sync and async
I need some helping to solve this issue I'm stuck with at work. 我需要一些帮助才能解决我在工作中遇到的问题。 We have an Web API in .NET Framework 4.7.1 (It has an API, Application, Core, Test projects).
我们在.NET Framework 4.7.1中有一个Web API(它有一个API,应用程序,核心,测试项目)。 The project is complex and it has code from 10+ different developers.
该项目很复杂,它包含来自10多个不同开发人员的代码。 We use Microsoft Dynamics D365 8.2 OnPremise for our data, so anytime we have to do CRUD operations we have to connect with the CRM via their SDK code.
我们使用Microsoft Dynamics D365 8.2 OnPremise来获取数据,因此,只要我们必须进行CRUD操作,我们就必须通过其SDK代码与CRM连接。 The project is hosted on IIS 8.5 Windwos Server 2012 R2 and the front-end is Angular 5 (we use the withCredentials option for API calls).
该项目托管在IIS 8.5 Windwos Server 2012 R2上,前端是Angular 5(我们使用withCredentials选项进行API调用)。 We have Windows Authentication and ASP.NET Impersonation turned on and all other Authetication methods disabled.
我们启用了Windows身份验证和ASP.NET模拟,并禁用了所有其他身份验证方法。 On our C# code, 99% of the times we connect to our CRM SDK we also need to impersonate the user, we do this by passing the username to get a Guid.
在我们的C#代码中,99%的时候我们连接到CRM SDK,我们还需要冒充用户,我们通过传递用户名来获取Guid。 This code has been working for a long time, until very recently we found out our code was setting the user incorrectly randomly.
此代码已经工作了很长时间,直到最近我们发现我们的代码是错误地随机设置用户。
The code that sometimes doesn't work is: 有时不起作用的代码是:
System.Security.Principal.WindowsPrincipal(System.Security.Principal.WindowsIdentity.GetCurrent()).Identity.Name
Most of the times we get the correct user but sometimes it gets the user running the process in IIS. 大多数情况下,我们获得了正确的用户,但有时它会让用户在IIS中运行该进程。
I also tried: 我也尝试过:
System.Web.HttpContext.Current.User.Identity.Name
But sometimes this is null 但有时这是空的
And lastly what I thought the solution was: 最后我认为解决方案是:
System.Threading.Thread.CurrentPrincipal.Identity.Name
This worked for many of my tests. 这适用于我的许多测试。 The problem is, after a while (I think if the service gets called inside a Task.Run(() => {}); block it gives an error: System.ObjectDisposedException: Safe handle has been closed
问题是,过了一会儿(我想如果服务在Task.Run(()=> {}内调用);阻止它会产生错误:System.ObjectDisposedException:安全句柄已关闭
I read the following articles to help: official Documentation about .net web api: https://docs.microsoft.com/en-us/aspnet/web-api/overview/security/authentication-and-authorization-in-aspnet-web-api 我阅读了以下文章以获得帮助:关于.net web api的官方文档: https : //docs.microsoft.com/en-us/aspnet/web-api/overview/security/authentication-and-authorization-in-aspnet-网络API
This post talking about a very similar issue: https://social.msdn.microsoft.com/Forums/vstudio/en-US/bca4556e-53f3-427c-a51a-9b955e2395e2/how-to-get-the-windows-identity-through-web-api-2-in-a-intranetlocal-network-setup?forum=wcf#89485c63-352b-434a-862b-8c5f4cec620c 这篇文章谈到一个非常类似的问题: https : //social.msdn.microsoft.com/Forums/vstudio/en-US/bca4556e-53f3-427c-a51a-9b955e2395e2/how-to-get-the-windows-identity -通过Web方式的API-2-IN-A-intranetlocal -网络设置?论坛= WCF#89485c63-352b-434A-862B-8c5f4cec620c
These two post about the Safe Handle has been closed: Retaining principal inside queued background work item Set Thread.CurrentPrincipal Asynchronously? 关于安全句柄的这两篇帖子已经关闭: 在校对后台工作项中保留主体 设置Thread.CurrentPrincipal异步?
which made me try to write some code like (kept the System.Threading.Thread.CurrentPrincipal.Identity.Name working but still throwing the error): 这使我尝试编写一些代码(保持System.Threading.Thread.CurrentPrincipal.Identity.Name工作,但仍然抛出错误):
ClaimsPrincipal principal = new ClaimsPrincipal(Thread.CurrentPrincipal);
// Save Total Payment Stream Payments (Async)
Task.Run(() =>
{
HttpContext.Current.User = new ClaimsPrincipal(new ClaimsPrincipal(new ClaimsIdentity(new[] { new Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", principal.Identity.Name) }, "auth")));
Thread.CurrentPrincipal = principal;
SaveTotalPaymentStream(opportunityTermId);
});
Any ideas or suggestions about this would be great. 任何有关这方面的想法或建议都会很棒。 Maybe I need something more complex like creating a custom Principal or maybe I'm just messing up the Task.Run (which I finally thought I had it figured out...)
也许我需要一些更复杂的东西,比如创建一个自定义的Principal,或者我只是弄乱了Task.Run(我终于认为我弄明白了......)
Thanks! 谢谢!
What I learned is that getting the logged on user in async methods can be pretty tricky. 我学到的是用异步方法获取登录用户可能非常棘手。 The HttpContext is pretty reliable for sync code and when I absolutely need the logged in user I just pass a variable into my async code.
HttpContext对于同步代码非常可靠,当我绝对需要登录用户时,我只是将一个变量传递给我的异步代码。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.