adr*_*nks 153 c# impersonation windows-security asp.net-web-api
我有一个与Windows服务对话的Web应用程序(在IIS中托管).Windows服务使用ASP.Net MVC Web API(自托管),因此可以使用JSON通过http进行通信.Web应用程序配置为进行模拟,其想法是向Web应用程序发出请求的用户应该是Web应用程序用来向服务发出请求的用户.结构如下所示:

(以红色突出显示的用户是以下示例中引用的用户.)
Web应用程序使用以下命令向Windows服务发出请求HttpClient:
var httpClient = new HttpClient(new HttpClientHandler()
{
UseDefaultCredentials = true
});
httpClient.GetStringAsync("http://localhost/some/endpoint/");
Run Code Online (Sandbox Code Playgroud)
这会向Windows服务发出请求,但不会正确传递凭据(服务将用户报告为IIS APPPOOL\ASP.NET 4.0).这不是我想要发生的事情.
如果我将上述代码更改为使用WebClient,则会正确传递用户的凭据:
WebClient c = new WebClient
{
UseDefaultCredentials = true
};
c.DownloadStringAsync(new Uri("http://localhost/some/endpoint/"));
Run Code Online (Sandbox Code Playgroud)
使用上述代码,服务将用户报告为向Web应用程序发出请求的用户.
我执行错误HttpClient导致它无法正确传递凭据(或者它是一个错误HttpClient),我做错了什么?
我想使用HttpClient它的原因是它有一个与s兼容的异步API Task,而WebClientasyc API需要用事件处理.
Sea*_*ean 118
您可以配置HttpClient为自动传递以下凭据:
myClient = new HttpClient(new HttpClientHandler() { UseDefaultCredentials = true })
Run Code Online (Sandbox Code Playgroud)
Jos*_*hua 59
我也有同样的问题.由于@tpeczek在以下SO文章中所做的研究,我开发了一个同步解决方案:无法使用HttpClient对ASP.NET Web Api服务进行身份验证
我的解决方案使用了一个WebClient,正如您正确指出的那样,它可以毫无问 原因HttpClient不起作用是因为Windows安全性禁用了在模拟帐户下创建新线程的能力(参见上面的SO文章.) HttpClient通过任务工厂创建新线程,从而导致错误. WebClient另一方面,在同一个线程上同步运行,从而绕过规则并转发其凭据.
尽管代码有效,但缺点是它不能正常工作.
var wi = (System.Security.Principal.WindowsIdentity)HttpContext.Current.User.Identity;
var wic = wi.Impersonate();
try
{
var data = JsonConvert.SerializeObject(new
{
Property1 = 1,
Property2 = "blah"
});
using (var client = new WebClient { UseDefaultCredentials = true })
{
client.Headers.Add(HttpRequestHeader.ContentType, "application/json; charset=utf-8");
client.UploadData("http://url/api/controller", "POST", Encoding.UTF8.GetBytes(data));
}
}
catch (Exception exc)
{
// handle exception
}
finally
{
wic.Undo();
}
Run Code Online (Sandbox Code Playgroud)
注意:需要NuGet包:Newtonsoft.Json,它与WebAPI使用的JSON序列化程序相同.
Bla*_*Spy 24
你要做的是让NTLM将身份转发到下一个服务器,这是它无法做到的 - 它只能进行模拟,只能让你访问本地资源.它不会让你跨越机器边界.Kerberos身份验证通过使用故障单支持委派(您需要),并且当链中的所有服务器和应用程序都已正确配置并且在域上正确设置Kerberos时,可以转发故障单.因此,简而言之,您需要从使用NTLM切换到Kerberos.
有关Windows可用的身份验证选项以及它们的工作原理,请访问:http: //msdn.microsoft.com/en-us/library/ff647076.aspx
小智 14
好的,感谢上面的所有贡献者.我使用的是.NET 4.6,我们也遇到了同样的问题.我花时间调试System.Net.Http,特别是HttpClientHandler,并发现以下内容:
if (ExecutionContext.IsFlowSuppressed())
{
IWebProxy webProxy = (IWebProxy) null;
if (this.useProxy)
webProxy = this.proxy ?? WebRequest.DefaultWebProxy;
if (this.UseDefaultCredentials || this.Credentials != null || webProxy != null && webProxy.Credentials != null)
this.SafeCaptureIdenity(state);
}
Run Code Online (Sandbox Code Playgroud)
所以在评估了ExecutionContext.IsFlowSuppressed()可能是罪魁祸首后,我将我们的模拟代码包装如下:
using (((WindowsIdentity)ExecutionContext.Current.Identity).Impersonate())
using (System.Threading.ExecutionContext.SuppressFlow())
{
// HttpClient code goes here!
}
Run Code Online (Sandbox Code Playgroud)
里面的代码SafeCaptureIdenity(不是我的拼写错误),抓住WindowsIdentity.Current()了我们冒充身份的身份.这是因为我们现在正在抑制流动.由于使用/ dispose,这在调用后重置.
它现在似乎对我们有用,p!
在.NET Core中,我设法System.Net.Http.HttpClient使用UseDefaultCredentials = true来通过来将经过身份验证的用户的Windows凭据传递到后端服务WindowsIdentity.RunImpersonated。
HttpClient client = new HttpClient(new HttpClientHandler { UseDefaultCredentials = true } );
HttpResponseMessage response = null;
if (identity is WindowsIdentity windowsIdentity)
{
await WindowsIdentity.RunImpersonated(windowsIdentity.AccessToken, async () =>
{
var request = new HttpRequestMessage(HttpMethod.Get, url)
response = await client.SendAsync(request);
});
}
Run Code Online (Sandbox Code Playgroud)
小智 5
在我在 Windows 服务中设置了可以访问互联网的用户后,它对我有用。
在我的代码中:
HttpClientHandler handler = new HttpClientHandler();
handler.Proxy = System.Net.WebRequest.DefaultWebProxy;
handler.Proxy.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials;
.....
HttpClient httpClient = new HttpClient(handler)
....
Run Code Online (Sandbox Code Playgroud)