C# HttpClient 刷新令牌策略

Phi*_*lon 8 c# httpclient delegatinghandler

由于微软建议HttpClient创建一次,并在整个项目的生命重用,我不知道如何更新DefaultRequestHeaders时,例如,令牌已过期,需要刷新。

DefaultRequestHeaders更不是线程安全的(据我所知)以及在那里定义的标头列表,由所有潜在的待处理请求共享。Clear()列表和Add()带有新标记的标题似乎不是明智之举。


更新

更准确地说,我不想/不需要为每个请求更改请求标头。仅当我获得 HTTP 401 状态代码时。

Bre*_*ann 6

当您在 DI 容器注册表阶段注册 IHttpClient 或使用其他模式(例如工厂或单例)返回带有自定义消息处理程序的 IHttpClient 实例时,将消息处理程序与您的 HttpClient 连接起来。检查出站呼叫并添加必要的标头。

https://docs.microsoft.com/en-us/aspnet/web-api/overview/advanced/httpclient-message-handlers

示例标头消息处理程序

class MessageHandler1 : DelegatingHandler
    {


    private int _count = 0;

    protected override Task<HttpResponseMessage> SendAsync(
        HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
    {
        System.Threading.Interlocked.Increment(ref _count);
        request.Headers.Add("X-Custom-Header", _count.ToString());
        return base.SendAsync(request, cancellationToken);
    }
}
Run Code Online (Sandbox Code Playgroud)

示例记录器消息处理程序:

class LoggingHandler : DelegatingHandler

{
    StreamWriter _writer;

public LoggingHandler(Stream stream)
{
    _writer = new StreamWriter(stream);
}

protected override async Task<HttpResponseMessage> SendAsync(
    HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
{
    var response = await base.SendAsync(request, cancellationToken);

    if (!response.IsSuccessStatusCode)
    {
        _writer.WriteLine("{0}\t{1}\t{2}", request.RequestUri, 
            (int)response.StatusCode, response.Headers.Date);
    }
    return response;
}

protected override void Dispose(bool disposing)
{
    if (disposing)
    {
        _writer.Dispose();
    }
    base.Dispose(disposing);
}
Run Code Online (Sandbox Code Playgroud)

}

将其添加到管道中

HttpClient client = HttpClientFactory.Create(new Handler1(), new Handler2(), new Handler3());
Run Code Online (Sandbox Code Playgroud)

线程问题

关于线程问题或并发性,方法HttpRequestMessage上的参数SendAsync将是每个请求。如果您将标头添加到request.Headers集合中,您将仅更新该请求实例的标头(即,不是全局)

或者在request.Headers实例上使用 Authorization 属性:

request.Headers.Authorization = new AuthenticationHeaderValue("bearer", bearerToken);
Run Code Online (Sandbox Code Playgroud)

请参阅下面的 MSDN 链接

https://msdn.microsoft.com/en-us/library/system.net.http.httprequestmessage

如果您使用DefaultRequestHeadersHttpClient 的静态、共享、单例、Lifestyle.Singleton 等实例,那么您将有线程问题并且需要适当的同步来更新DefaultRequestHeaders集合。