C# 具有不同身份验证头的HttpClient单实例

C# 具有不同身份验证头的HttpClient单实例,c#,.net,oauth,authorization,dotnet-httpclient,C#,.net,Oauth,Authorization,Dotnet Httpclient,鉴于.net HttpClient在设计时考虑到了重用,并打算在短期实例中使用。在为多个用户调用端点时,您希望使用不同的承载令牌(或任何授权头)对给定端点进行restful调用的指导原则有哪些 private void CallEndpoint(string resourceId, string bearerToken) { httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(&

鉴于.net HttpClient在设计时考虑到了重用,并打算在短期实例中使用。在为多个用户调用端点时,您希望使用不同的承载令牌(或任何授权头)对给定端点进行restful调用的指导原则有哪些

private void CallEndpoint(string resourceId, string bearerToken) {
  httpClient.DefaultRequestHeaders.Authorization =
    new AuthenticationHeaderValue("bearer", bearerToken);
  var response = await httpClient.GetAsync($"resource/{resourceid}");
}
鉴于上述代码可以由web应用程序上任意数量的线程调用,因此很可能第一行中设置的头与调用资源时使用的头不同

在不使用锁和维护无状态web应用程序的情况下,为单个端点创建和处理HttpClient的推荐方法是什么(我目前的做法是为每个端点创建一个客户端)


生命周期

虽然HttpClient确实间接实现了IDisposable 接口,HttpClient的建议用法是不处置它 每次请求之后。HttpClient对象旨在作为 只要应用程序需要发出HTTP请求。有目标的 “跨多个请求存在”允许设置一个位置 DefaultRequestHeader并防止您重新指定内容 就像CredentialCache和CookieContainer一样 HttpWebRequest需要


如果您的头通常是相同的,那么您可以设置
DefaultRequestHeaders
。但是您不需要使用该属性来指定头。正如您所确定的,如果您将有多个线程使用同一个客户机,那么这将不起作用。对一个线程上的默认头所做的更改将影响在其他线程上发送的请求

尽管您可以在客户机上设置默认头并将其应用于每个请求,但头实际上是请求的属性。因此,当标题特定于请求时,您只需将其添加到请求中即可

request.Headers.Authorization = new AuthenticationHeaderValue("bearer", bearerToken);
这意味着您不能使用不涉及创建
HttpRequest
的简化方法。你需要使用

public Task<HttpResponseMessage> SendAsync(HttpRequestMessage request)
然后,可以像以下那样使用它们:

var response = await httpClient.GetAsync("token",
    x => x.Headers.Authorization = new AuthenticationHeaderValue("basic", clientSecret));

如果您的头通常是相同的,那么您可以设置
DefaultRequestHeaders
。但是您不需要使用该属性来指定头。正如您所确定的,如果您将有多个线程使用同一个客户机,那么这将不起作用。对一个线程上的默认头所做的更改将影响在其他线程上发送的请求

尽管您可以在客户机上设置默认头并将其应用于每个请求,但头实际上是请求的属性。因此,当标题特定于请求时,您只需将其添加到请求中即可

request.Headers.Authorization = new AuthenticationHeaderValue("bearer", bearerToken);
这意味着您不能使用不涉及创建
HttpRequest
的简化方法。你需要使用

public Task<HttpResponseMessage> SendAsync(HttpRequestMessage request)
然后,可以像以下那样使用它们:

var response = await httpClient.GetAsync("token",
    x => x.Headers.Authorization = new AuthenticationHeaderValue("basic", clientSecret));


你说的是数量相对较少的不同身份验证头或批,例如每个用户都是唯一的吗?@ToddMenier-这将是每个用户的唯一头。这将是用户oauth令牌。我认为斯科特·汉宁让我走上了正确的道路。看起来一些扩展方法将是合适的。你好@Bronumski,你能分享一下你解决这个问题的方法吗?我有相同的问题,多个线程添加相同的标题,但内容不同。@LuisMejia-我用一个例子更新了scotts的答案,说明了我是如何获取和发布的。同样的原则也适用于您想要实现的任何其他方法。扩展方法包括一个操作,允许您在发送HttpRequest之前对其进行操作。@Bronumski感谢您的回答。。。似乎我也在使用sendasync并将请求作为参数与自定义头一起传递。你说的是数量相对较少的不同身份验证头或批,例如对每个用户都是唯一的吗?@ToddMenier-对每个用户都是唯一的头。这将是用户oauth令牌。我认为斯科特·汉宁让我走上了正确的道路。看起来一些扩展方法将是合适的。你好@Bronumski,你能分享一下你解决这个问题的方法吗?我有相同的问题,多个线程添加相同的标题,但内容不同。@LuisMejia-我用一个例子更新了scotts的答案,说明了我是如何获取和发布的。同样的原则也适用于您想要实现的任何其他方法。扩展方法包括一个操作,允许您在发送HttpRequest之前对其进行操作。@Bronumski感谢您的回答。。。看起来我也在用类似的方法使用sendasync并将请求作为带有自定义头的参数传递。很好的解决方案。刚刚实施。在公共静态任务GetAsync(此HttpClient HttpClient,string uri,string token,CancellationToken CancellationToken){返回HttpClient.GetAsync(uri,x=>SetToken(x,token),CancellationToken);}void SetToken(HttpRequestMessage,string token,string type=“Bearer”)如何处理
HttpClientHandler.Proxy
HttpClientHandler.CookieContainer
以及
HttpClientHandler
的其他属性,这些属性不能在
HttpRequestMessage
中设置?(或者他们可以?)@DavidS。您找到代理的解决方案了吗?对于代理、cookiecontainer等,如果您对单个请求有特定需求,我相信建议您使用命名或类型化的客户端,这些客户端具有您对这些特定请求所需的配置,然后您可以对所有其他请求使用未命名的客户端@hemp-我同意,但该文档适用于
Microsoft.Extensions.DependencyInjection
IServiceCollection
),或者至少我们不太清楚如何将其与不同的IoC容器一起使用,或者不使用。很好的解决方案。刚刚实施。在公共静态任务GetAsync(此HttpClient)下面添加了以下模式的快捷方式