You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 15:53:15