在Refit中结合Polly重试时无法刷新Token的问题
问题分析与解决方案
你的问题核心在于:重试时使用的仍是最初调用接口时传入的旧Token。因为Device_GetAllAsync(await GetToken())在第一次调用前就已经获取了Token并传入方法,Polly重试只是重复执行这个已经绑定了旧Token的方法调用,不会重新执行await GetToken(),所以哪怕你刷新了Token,重试请求依然用的是旧值。
解决方案:改用请求头自动注入Token,而非方法参数传递
1. 修改Refit接口,移除Token参数
把Token从方法参数中移除,改为通过请求头自动添加:
public interface IHomeMonitorRestClient { [Get("/Device")] Task<IEnumerable<Model.Device>> Device_GetAllAsync(); }
2. 新增Token注入Handler
创建一个DelegatingHandler,负责在每次请求(包括重试)时自动从AuthService获取最新Token并添加到请求头:
public class TokenAuthorizationHandler : DelegatingHandler { private readonly AuthService _authService; public TokenAuthorizationHandler(AuthService authService) { _authService = authService; } protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { // 每次请求都获取当前最新的Token var currentToken = await _authService.GetCurrentToken(); request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", currentToken); return await base.SendAsync(request, cancellationToken); } }
注:需要在AuthService中新增GetCurrentToken()方法,返回当前有效的Token(刷新后会更新这个值)
3. 调整Rest客户端注册逻辑
把Token注入Handler添加到HttpClient管道中,同时保留原有Polly策略:
private static void AddRestClient(IServiceCollection services, string hMClientBaseUrl, AuthService authService) { var unauthPolicy = Policies.GetUnauthPolicy(authService); services.AddRefitClient<IHomeMonitorRestClient>(new RefitSettings { ContentSerializer = new NewtonsoftJsonContentSerializer(DefaultJsonSettings.Settings), }) .ConfigureHttpClient(c => c.BaseAddress = new Uri(hMClientBaseUrl)) .ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler { ServerCertificateCustomValidationCallback = (message, cert, chain, sslErrors) => true }) .AddHttpMessageHandler(() => new TokenAuthorizationHandler(authService)) // 注入Token处理Handler .AddPolicyHandler(unauthPolicy); }
4. 简化API调用代码
现在调用接口不需要手动传Token了:
var devices = await _hmRestClient.Device_GetAllAsync();
5. 保留原有Polly策略逻辑
你的重试策略无需大改,只要确保RefreshToken()方法能正确更新AuthService内部的Token存储即可:
public static AsyncRetryPolicy<HttpResponseMessage> GetUnauthPolicy(AuthService authService) { return Policy.HandleResult<HttpResponseMessage>(r => r.StatusCode == HttpStatusCode.Unauthorized) .WaitAndRetryAsync(3, retryAttempt => TimeSpan.FromSeconds(1), async (response, timespan, retryNo, context) => { await authService.RefreshToken(); // 刷新后,AuthService内部的Token会更新 }); }
为什么这个方案能解决循环问题?
每次请求(包括Polly触发的重试)都会经过TokenAuthorizationHandler,它会实时从AuthService获取最新的Token,刷新Token后的重试请求自然会使用新Token,不会再重复触发未授权错误。
内容的提问来源于stack exchange,提问作者jason.kaisersmith
相关产品推荐
相关产品推荐

