Refit调用Keycloak Admin API时存在客户端缓存异常问题
使用Refit调用Keycloak Admin API时的缓存问题
问题详情
在Keycloak中创建新领域后立即调用RealmsAll()方法,返回的仍是旧的领域列表(如原本5个,新增后应6个却仍返回5个),但存在以下例外情况:
- 直接使用HttpClient调用可正常获取最新数据(无缓存)
- Postman请求可正常获取最新数据
- 重启应用后调用
RealmsAll()能返回正确结果
这表明问题出在Refit的客户端缓存,而非服务端。ClientsAll3()方法也存在相同问题。
当前配置
Refit接口
[Headers("Accept: application/json")] [Get("/admin/realms")] Task<IApiResponse<ICollection<RealmRepresentation>>> RealmsAll([Query] bool? briefRepresentation);
服务注册
services.AddTransient<NoCacheHandler>(); var refitSettings = new RefitSettings { ContentSerializer = new SystemTextJsonContentSerializer(new JsonSerializerOptions { PropertyNameCaseInsensitive = false, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull }) }; services.AddRefitClient<IKeycloakAdminRESTAPI>(refitSettings) .AddHttpMessageHandler<KeycloakAdminAuthenticationHandler>() .AddHttpMessageHandler<NoCacheHandler>() .ConfigureHttpClient((serviceProvider, config) => { var keycloakOptions = serviceProvider.GetRequiredService<IOptions<KeycloakOptions>>(); config.BaseAddress = new Uri(keycloakOptions.Value.Url); config.DefaultRequestHeaders.CacheControl = new CacheControlHeaderValue { NoCache = true, NoStore = true, MustRevalidate = true, MaxAge = TimeSpan.Zero }; config.DefaultRequestHeaders.Pragma.ParseAdd("no-cache"); });
自定义NoCacheHandler
public class NoCacheHandler : DelegatingHandler { protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { // 添加无缓存请求头 request.Headers.Add("Cache-Control", "no-cache, no-store, must-revalidate"); request.Headers.Add("Pragma", "no-cache"); // 为URL添加唯一时间戳参数 var uriBuilder = new UriBuilder(request.RequestUri); var query = System.Web.HttpUtility.ParseQueryString(uriBuilder.Query); query["_t"] = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds().ToString(); uriBuilder.Query = query.ToString(); request.RequestUri = uriBuilder.Uri; var response = await base.SendAsync(request, cancellationToken); // 清除响应中的缓存相关头 response.Headers.Remove("ETag"); response.Headers.CacheControl = new System.Net.Http.Headers.CacheControlHeaderValue { NoCache = true, NoStore = true, MustRevalidate = true }; return response; } }
已尝试方案
- 添加
Cache-Control: no-cache, no-store, must-revalidate请求头 - 添加
Pragma: no-cache请求头 - 为每个请求添加唯一时间戳查询参数
- 移除响应中的ETag头
- 配置HttpClient的无缓存设置
- 使用自定义HttpMessageHandler修改请求/响应
- 设置
ConnectionClose=false等其他HttpClient配置
尝试在Refit中禁用客户端缓存无效,但直接使用HttpClient可正常工作。
环境
.NET 8、Refit 8.0.0、Keycloak Admin REST API、Windows开发环境
内容的提问来源于stack exchange,提问作者Alptekin
相关产品推荐
相关产品推荐

