小编典典

如何让 HttpClient 与请求一起传递凭据?

all

我有一个与 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/");

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

如果我将上面的代码更改为使用 a WebClient,则用户的凭据将正确传递:

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

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

我做错了什么HttpClient导致它无法正确传递凭据(或者它是一个错误HttpClient)?

我想使用的原因HttpClient是它有一个与Tasks 配合得很好的异步 API,而 的WebClient异步 API 需要用事件来处理。


阅读 72

收藏
2022-07-28

共1个答案

小编典典

我的解决方案使用 a 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();
}

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

2022-07-28