如何让 HttpClient 与请求一起传递凭据? [英] How to get HttpClient to pass credentials along with the request?

查看:43
本文介绍了如何让 HttpClient 与请求一起传递凭据?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个与 Windows 服务通信的 Web 应用程序(托管在 IIS 中).Windows 服务使用 ASP.Net MVC Web API(自托管),因此可以使用 JSON 通过 http 进行通信.Web 应用程序配置为进行模拟,其想法是向 Web 应用程序发出请求的用户应该是 Web 应用程序用来向服务发出请求的用户.结构如下:

I have a web application (hosted in IIS) that talks to a Windows service. The Windows service is using the ASP.Net MVC Web API (self-hosted), and so can be communicated with over http using JSON. The web application is configured to do impersonation, the idea being that the user who makes the request to the web application should be the user that the web application uses to make the request to the service. The structure looks like this:

(红色突出显示的用户是以下示例中所指的用户.)

Web 应用程序使用 HttpClient 向 Windows 服务发出请求:

The web application makes requests to the Windows service using an HttpClient:

var httpClient = new HttpClient(new HttpClientHandler() 
                      {
                          UseDefaultCredentials = true
                      });
httpClient.GetStringAsync("http://localhost/some/endpoint/");

这会向 Windows 服务发出请求,但没有正确传递凭据(服务将用户报告为 IIS APPPOOLASP.NET 4.0).这不是我想要发生的.

This makes the request to the Windows service, but does not pass the credentials over correctly (the service reports the user as IIS APPPOOLASP.NET 4.0). This is not what I want to happen.

如果我将上述代码更改为使用 WebClient 相反,正确传递了用户的凭据:

If I change the above code to use a WebClient instead, the credentials of the user are passed correctly:

WebClient c = new WebClient
                   {
                       UseDefaultCredentials = true
                   };
c.DownloadStringAsync(new Uri("http://localhost/some/endpoint/"));

使用上述代码,服务将用户报告为向 Web 应用程序发出请求的用户.

With the above code, the service reports the user as the user who made the request to the web application.

我在 HttpClient 实现上做错了什么导致它无法正确传递凭据(或者它是 HttpClient 的错误)代码>)?

What am I doing wrong with the HttpClient implementation that is causing it to not pass the credentials correctly (or is it a bug with the HttpClient)?

我想使用 HttpClient 的原因是它有一个异步 API,可以很好地与 Tasks 配合使用,而 WebClientcode> 的异步 API 需要使用事件处理.

The reason I want to use the HttpClient is that it has an async API that works well with Tasks, whereas the WebClient's asyc API needs to be handled with events.

推荐答案

我也遇到了同样的问题.由于@tpeczek 在以下 SO 文章中进行的研究,我开发了一个同步解决方案:Unable to authentication to ASP.NET Web Api service withHttpClient

I was also having this same problem. I developed a synchronous solution thanks to the research done by @tpeczek in the following SO article: Unable to authenticate to ASP.NET Web Api service with HttpClient

我的解决方案使用 WebClient,正如您正确指出的那样,它可以毫无问题地传递凭据.HttpClient 不起作用的原因是因为 Windows 安全禁用了在模拟帐户下创建新线程的能力(请参阅上面的 SO 文章.)HttpClient 通过任务工厂从而导致错误.WebClient 另一方面,在同一线程上同步运行,从而绕过规则并转发其凭据.

My solution uses a WebClient, which as you correctly noted passes the credentials without issue. The reason HttpClient doesn't work is because of Windows security disabling the ability to create new threads under an impersonated account (see SO article above.) HttpClient creates new threads via the Task Factory thus causing the error. WebClient on the other hand, runs synchronously on the same thread thereby bypassing the rule and forwarding its credentials.

虽然代码有效,但缺点是它不能异步工作.

Although the code works, the downside is that it will not work async.

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();
}

注意:需要 NuGet 包:Newtonsoft.Json,它与 WebAPI 使用的 JSON 序列化程序相同.

Note: Requires NuGet package: Newtonsoft.Json, which is the same JSON serializer WebAPI uses.

这篇关于如何让 HttpClient 与请求一起传递凭据?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆