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

如何自动刷新Access Token?Blazor应用令牌续期问题

实现Blazor应用中Access Token的自动刷新

1. 先加上offline_access权限范围

要拿到刷新令牌(Refresh Token),必须在认证请求里包含offline_access这个权限,你当前的配置只加了API的权限,补上这行:

options.Scope.Add("offline_access"); // 刷新令牌必备的权限
options.Scope.Add("api://xxxxx/api_access"); // 保留原有的API权限

2. 给Cookie认证加令牌刷新逻辑

通过Cookie认证的OnValidatePrincipal事件,每次验证用户身份时检查Access Token是否过期,过期了就用Refresh Token去换新的令牌,再更新认证票据:

修改AddCookie的配置:

.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options =>
{
    options.Events = new CookieAuthenticationEvents
    {
        async OnValidatePrincipal = async context =>
        {
            // 从当前认证票据里取Access Token和Refresh Token
            var accessToken = context.Properties.GetTokenValue("access_token");
            var refreshToken = context.Properties.GetTokenValue("refresh_token");

            if (string.IsNullOrEmpty(accessToken) || string.IsNullOrEmpty(refreshToken))
            {
                // 没拿到令牌,直接拒绝身份,让用户重新登录
                context.RejectPrincipal();
                return;
            }

            // 检查Access Token是否还没过期
            var tokenHandler = new JwtSecurityTokenHandler();
            var jwtToken = tokenHandler.ReadJwtToken(accessToken);
            if (jwtToken.ValidTo > DateTime.UtcNow)
            {
                // 令牌还能用,不用处理
                return;
            }

            // 调用认证服务器的令牌刷新接口
            var config = context.HttpContext.RequestServices.GetRequiredService<IConfiguration>();
            var tokenEndpoint = $"{config["Authority"]}/connect/token";
            var client = new HttpClient();
            var request = new HttpRequestMessage(HttpMethod.Post, tokenEndpoint);
            request.Content = new FormUrlEncodedContent(new Dictionary<string, string>
            {
                ["grant_type"] = "refresh_token",
                ["client_id"] = "xxxxx", // 替换成你的ClientId
                ["client_secret"] = "xxxxx", // 替换成你的ClientSecret
                ["refresh_token"] = refreshToken,
                ["scope"] = "api://xxxxx/api_access offline_access" // 和之前请求的权限保持一致
            });

            var response = await client.SendAsync(request);
            if (!response.IsSuccessStatusCode)
            {
                // 刷新失败,拒绝身份,引导用户重新登录
                context.RejectPrincipal();
                return;
            }

            var tokenResponse = await response.Content.ReadFromJsonAsync<Dictionary<string, string>>();
            if (tokenResponse == null || !tokenResponse.ContainsKey("access_token"))
            {
                context.RejectPrincipal();
                return;
            }

            // 更新票据里的令牌信息
            context.Properties.UpdateTokenValue("access_token", tokenResponse["access_token"]);
            if (tokenResponse.ContainsKey("refresh_token"))
            {
                context.Properties.UpdateTokenValue("refresh_token", tokenResponse["refresh_token"]);
            }

            // 更新票据的过期时间(跟着新的Access Token走)
            var newJwtToken = tokenHandler.ReadJwtToken(tokenResponse["access_token"]);
            context.Properties.ExpiresUtc = newJwtToken.ValidTo;

            // 标记需要重新生成认证票据
            context.ShouldRenew = true;
        }
    };
})

3. 更省心的方式:用HttpClient自动管令牌

在Blazor里,推荐配置专门的HttpClient,让它自动处理令牌的获取和刷新,不用手动调用GetTokenAsync:

注册带令牌处理的HttpClient

builder.Services.AddHttpClient("ApiClient", client =>
{
    client.BaseAddress = new Uri("你的API基础地址");
})
.AddHttpMessageHandler<BaseAddressAuthorizationMessageHandler>();

builder.Services.AddScoped(sp => sp.GetRequiredService<IHttpClientFactory>().CreateClient("ApiClient"));
builder.Services.AddAuthorization();

在组件里直接用这个HttpClient

@inject HttpClient ApiClient

// 调用API的时候直接用ApiClient就行,它会自动搞定令牌的事儿
var response = await ApiClient.GetFromJsonAsync<YourResponseType>("api/endpoint");

这种方式会自动依托ASP.NET Core的认证系统处理刷新逻辑,不用自己写一堆代码,更适合Blazor的开发模式。

几个要注意的点

  • 得确认你的认证服务器支持refresh_token授权类型,而且已经给你的客户端开了使用Refresh Token的权限。
  • Refresh Token可能有过期时间或者使用次数限制,要是刷新失败了,就得引导用户重新登录。
  • 生产环境里尽量用IHttpClientFactory管理HttpClient实例,别随便新建客户端,避免资源浪费。

内容的提问来源于stack exchange,提问作者Krafter

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 13:43:14