Using RunImpersonated for an HttpClient call fails for a NUnit test, but works in Console

让人想犯罪 __ 提交于 2021-01-05 08:53:45

问题


I need to have my tests run as a testing account. To accomplish that I setup to the following code to create a handle into my testing account:

SafeAccessTokenHandle testAccountHandle;

bool returnValue = LogonUser("TestAccount", "myDom.net", 
       "pass", 2, 0, out testAccountHandle);

I can then make a call to load a URL:

HttpResponseMessage response = null;

await WindowsIdentity.RunImpersonated<Task>(testAccountHandle, async () =>
{
    var url = "https://accounts.google.com/.well-known/openid-configuration";
    response = await httpClient.GetAsync(url);
});
testAccountHandle.Dispose();

When I run this in a console application, it works just fine. (Likewise in LinqPad.)

However when I run this code in an NUnit test, I get the following error:

System.Net.Sockets.SocketException : This is usually a temporary error during hostname resolution and means that the local server did not receive a response from an authoritative server.

It says it is usually a temporary error, but it happens every single time I run impersonated in the NUnit Test, and never when I run in the Console. It also never happens when I run in the NUnit test if I am not running impersonated. (In short it ONLY happens when in an NUnit Test and Impersonated.)

I am not sure how to go about debugging this. It seems clear that NUnit does not like my impersonation, but I am not sure what to do about it.

How can I make a successful HttpClient.GetAsync call while using RunImpersonated in an NUnit test?

NOTE: Full repro code can be found here: https://github.com/nunit/nunit/issues/3672


回答1:


This appears to be a bug with .NET Core. See the open issue and discussion here: https://github.com/dotnet/runtime/issues/29935

It seems that WindowsIdentity.RunImpersonated() works differently in .NET Core compared with .NET Framework. This is causing a variety of issues including one affecting ASP.NET Core, #29351.

There is some difference in the way that the identity token permissions are getting set on the impersonated token. This is causing "access denied" issues in a variety of ways.

Workaround

Issue #29351 from ASP.NET Core references this exact error message and contains a workaround. Setting the environment variable DOTNET_SYSTEM_NET_HTTP_USESOCKETSHTTPHANDLER to 0 disables the SocketsHttpHandler and makes this problem go away. For example, the following works without the error:

Environment.SetEnvironmentVariable("DOTNET_SYSTEM_NET_HTTP_USESOCKETSHTTPHANDLER", "0");
HttpResponseMessage response = null;

await WindowsIdentity.RunImpersonated<Task>(testAccountHandle, async () =>
{
    var url = "https://accounts.google.com/.well-known/openid-configuration";
    response = await httpClient.GetAsync(url);
});

You may need to make considerations for only setting this environment variable for this specific test and not for every test. I'm not sure what the impacts of disabling the SocketsHttpHandler are, so use the workaround at your own risk.



来源:https://stackoverflow.com/questions/64902793/using-runimpersonated-for-an-httpclient-call-fails-for-a-nunit-test-but-works-i

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!