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

.NET Core Web API中JWT闲置快速过期问题求助

嘿,这个问题我之前也踩过坑!核心是你搞混了JWT本身的过期机制和Cookie/Session的过期机制,这俩完全是两回事儿,咱们一步步理清楚:

问题根源拆解

首先,JWT是无状态令牌,它的过期时间是在生成时就写死在token的exp字段里的——你生成代码里已经设了expires: DateTime.UtcNow.AddYears(1),那这个token本身确实是1年后才会过期。那为啥闲置几分钟就失效?

看你的启动代码,你同时配置了JWT Bearer认证、Cookie认证和Session,问题就出在这儿:你大概率是把JWT存在了Cookie或者Session里,而Cookie/Session的过期时间设的是60分钟,Cookie过期了,你拿不到token了,不是JWT本身过期。

另外,SlidingExpiration是Cookie认证的特性,和JWT半毛钱关系没有——它只是帮你延长Cookie的有效期,不是更新JWT的exp字段。你发虚拟请求能维持有效性,其实是在刷新Cookie的过期时间,不是JWT的。

解决方案分两种场景

根据你的需求(关闭网页后token仍有效),分两种情况处理:

场景1:纯Web API(前端是SPA/小程序等)

纯API场景根本不需要Cookie和Session,直接让前端把JWT存在localStorage里,每次请求放在Authorization头里(格式是Bearer <token>)。这样即使关闭网页,localStorage里的token还在,只要没到exp时间就能继续用。

修改你的启动代码,去掉所有Cookie/Session相关配置,只保留JWT Bearer:

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(x => {
        string secretKeyStr = Configuration.GetValue<string>("SecretKey");
        byte[] secretKey = Encoding.ASCII.GetBytes(secretKeyStr);
        x.RequireHttpsMetadata = false;
        x.SaveToken = true;
        x.TokenValidationParameters = new TokenValidationParameters {
            ValidateIssuerSigningKey = true,
            IssuerSigningKey = new SymmetricSecurityKey(secretKey),
            ValidateIssuer = false,
            ValidateAudience = false,
            RequireExpirationTime = true,
            ValidateLifetime = true,
            ClockSkew = TimeSpan.FromDays(1),
        };
    });

// 删掉这些不需要的配置:
// services.AddCookie(...);
// services.Configure<CookiePolicyOptions>(...);
// services.AddDistributedMemoryCache();
// services.AddSession(...);
// services.ConfigureApplicationCookie(...);

场景2:必须用Cookie存储JWT(比如传统MVC/混合场景)

如果一定要用Cookie存JWT,那得调整Cookie配置,让它成为持久Cookie(默认Cookie是会话级的,关闭浏览器就失效),并且Cookie的过期时间要和JWT的exp字段匹配:

services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
    .AddJwtBearer(x => {
        string secretKeyStr = Configuration.GetValue<string>("SecretKey");
        byte[] secretKey = Encoding.ASCII.GetBytes(secretKeyStr);
        x.RequireHttpsMetadata = false;
        x.SaveToken = true;
        x.TokenValidationParameters = new TokenValidationParameters {
            ValidateIssuerSigningKey = true,
            IssuerSigningKey = new SymmetricSecurityKey(secretKey),
            ValidateIssuer = false,
            ValidateAudience = false,
            RequireExpirationTime = true,
            ValidateLifetime = true,
            ClockSkew = TimeSpan.FromDays(1),
        };
    })
    .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options => {
        // Cookie过期时间和JWT一致,设为1年
        options.ExpireTimeSpan = TimeSpan.FromYears(1);
        // 开启滑动过期,每次请求自动刷新Cookie过期时间
        options.SlidingExpiration = true;
        // 关键:设置Cookie为持久Cookie,关闭浏览器后不会立即失效
        options.Cookie.Expiration = TimeSpan.FromYears(1);
        // 其他安全配置按需调整
        options.Cookie.SameSite = SameSiteMode.None;
        options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
        options.Cookie.IsEssential = true;
        options.Cookie.HttpOnly = true;
    });

// 如果用了ASP.NET Core Identity,同步调整ApplicationCookie配置
services.ConfigureApplicationCookie(options => {
    options.SlidingExpiration = true;
    options.ExpireTimeSpan = TimeSpan.FromYears(1);
    options.Cookie.Expiration = TimeSpan.FromYears(1);
});

额外提醒:关于滑动过期的替代方案

如果你的需求是“用户活跃时自动延长token有效期”,JWT本身不支持滑动过期(因为无状态,服务器不存token状态),这时候应该实现Refresh Token机制:

  1. 生成JWT时同时生成一个Refresh Token(有效期更长,比如7天),存在持久Cookie里
  2. 当JWT快过期时,客户端用Refresh Token请求新的JWT
  3. 服务器验证Refresh Token有效后,返回新的JWT,这样用户不用重新登录

这个方案比用虚拟请求维持Cookie有效期更优雅,也更安全。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 13:02:28