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

.NET 7 WebAPI中JwtBearerEvents.OnAuthenticationFailed偶发未触发问题咨询

JWT刷新令牌机制偶发失效问题的解决方案

问题根源

你遇到的核心问题是:Chrome浏览器会自动删除已过期的Cookie。当JWT令牌过期后稍久(1-2秒),浏览器不再发送JWT Cookie到后端,导致JwtBearer中间件因未检测到令牌,根本不会进入验证流程,自然OnAuthenticationFailed事件不会触发,刷新逻辑也就无法执行。

关于OnAuthenticationFailed判断过期的合理性

用OnAuthenticationFailed事件判断JWT过期绝非最优方案。这个事件的触发前提是:后端收到了JWT令牌,但验证过程中出错(比如过期、签名无效等)。一旦浏览器因为Cookie过期停止发送令牌,中间件连验证环节都不会进入,事件就彻底失效了,完全依赖浏览器的行为,可靠性极低。

更可靠的替代方案

1. 前端主动预判令牌过期,提前刷新

在前端解析JWT的exp字段(过期时间戳),每次发起业务请求前,先检查令牌剩余有效期:

  • 如果剩余时间小于阈值(比如30秒),先调用刷新令牌接口获取新的JWT,再发送业务请求;
  • 如果令牌已过期,直接触发刷新流程。

这种方式完全不依赖浏览器是否发送过期Cookie,从源头避免了后端收不到令牌的情况,流程最可控。

2. 自定义全局中间件,接管令牌验证与刷新

绕过JwtBearer中间件的事件机制,自定义一个前置中间件,统一处理令牌逻辑:

  1. 从请求中读取JWT令牌(Cookie或请求头),验证其有效性;
  2. 如果JWT无效/不存在,读取Refresh Token Cookie;
  3. 验证Refresh Token的有效性,若有效则生成新的JWT和Refresh Token,更新客户端Cookie;
  4. 将新的JWT注入到请求头中,让后续的JwtBearer中间件能正常识别;
  5. 如果Refresh Token也无效,返回401要求重新登录。

示例核心代码:

public async Task InvokeAsync(HttpContext context)
{
    var jwtCookie = context.Request.Cookies["JwtToken"];
    var refreshToken = context.Request.Cookies["RefreshToken"];

    // 检查JWT是否有效
    var isJwtValid = ValidateJwt(jwtCookie);
    if (!isJwtValid && !string.IsNullOrEmpty(refreshToken))
    {
        // 验证刷新令牌并生成新令牌
        var newTokens = await RefreshTokens(refreshToken);
        if (newTokens != null)
        {
            // 更新Cookie
            context.Response.Cookies.Append("JwtToken", newTokens.Jwt, new CookieOptions { Expires = DateTime.UtcNow.AddSeconds(10), HttpOnly = true, Secure = true });
            context.Response.Cookies.Append("RefreshToken", newTokens.RefreshToken, new CookieOptions { Expires = DateTime.UtcNow.AddDays(10), HttpOnly = true, Secure = true });
            // 将新JWT注入请求头,供后续中间件使用
            context.Request.Headers.Authorization = $"Bearer {newTokens.Jwt}";
        }
        else
        {
            // 刷新令牌无效,返回401
            context.Response.StatusCode = StatusCodes.Status401Unauthorized;
            return;
        }
    }

    await _next(context);
}

3. 调整JWT Cookie的过期时间(临时 workaround)

把JWT Cookie的过期时间设置得比JWT本身的有效期稍长(比如JWT有效期10秒,Cookie设为15秒)。这样即使JWT过期了,Cookie还未被浏览器删除,依然会发送到后端,触发OnAuthenticationFailed事件,保证刷新逻辑能执行。

但这只是权宜之计,本质还是依赖浏览器的Cookie策略,不如前两种方案可靠。

4. 解耦刷新逻辑与JWT验证

后端处理请求时,不依赖JWT是否存在/有效,只要Refresh Token有效,就直接刷新JWT:

  • 无论请求中是否携带JWT,先检查Refresh Token的有效性;
  • 若Refresh Token有效,直接生成新的JWT和Refresh Token,更新Cookie后继续处理请求;
  • 只有当Refresh Token也无效时,才返回401。

这种方式彻底摆脱了对JWT验证流程的依赖,刷新逻辑的触发更稳定。

额外注意事项

  • Refresh Token必须存储在HttpOnly、Secure、SameSite=Strict/Lax的Cookie中,防止XSS和CSRF攻击;
  • 每次刷新令牌时,要生成新的Refresh Token并作废旧的,避免令牌复用;
  • 前端要处理刷新令牌失败的情况(比如Refresh Token过期),此时引导用户重新登录。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 04:20:24