ASP.NET Core会话1小时过期,如何延长或使用刷新令牌?
解决ASP.NET Core中Firebase认证会话持久化问题
一、使用Firebase刷新令牌自动续期ID Token
Firebase的ID Token默认1小时过期,仅延长ASP.NET Core会话时长无法解决令牌本身失效的问题,必须利用**刷新令牌(Refresh Token)**自动获取新的ID Token,维持用户登录状态。
1. 登录时存储必要信息
修改登录代码,除ID Token外,额外保存刷新令牌和令牌过期时间:
try { var fbAuthLink = await auth.SignInWithEmailAndPasswordAsync(account.Email, account.Password); string idToken = fbAuthLink.FirebaseToken; string refreshToken = fbAuthLink.RefreshToken; // 计算令牌过期时间(当前UTC时间 + 有效期秒数) var expiresAt = DateTime.UtcNow.AddSeconds(fbAuthLink.ExpiresIn); if (!string.IsNullOrEmpty(idToken)) { // 存储到会话 HttpContext.Session.SetString("_UserToken", idToken); HttpContext.Session.SetString("_RefreshToken", refreshToken); HttpContext.Session.SetString("_TokenExpiresAt", expiresAt.ToString("o")); // 用ISO格式存储时间 var a = _accountRepo.GetAccountByUID(fbAuthLink.User.LocalId); if (!a.IsSubscribed) { return RedirectToAction("Checkout", "Stripe"); } return RedirectToAction("Index"); } else { return View(); } } catch (Exception ex) { ModelState.AddModelError("", "登录失败:" + ex.Message); return View(); }
2. 实现自动续期逻辑
创建令牌检查与续期方法,通过中间件或动作过滤器在每次请求前执行:
public async Task RefreshTokenIfNeeded(HttpContext context, FirebaseAuthProvider authProvider) { var idToken = context.Session.GetString("_UserToken"); var refreshToken = context.Session.GetString("_RefreshToken"); var expiresAtStr = context.Session.GetString("_TokenExpiresAt"); // 验证存储信息有效性 if (string.IsNullOrEmpty(idToken) || string.IsNullOrEmpty(refreshToken) || !DateTime.TryParse(expiresAtStr, out var expiresAt)) { // 无有效令牌,跳转登录页 context.Response.Redirect("/Account/Login"); return; } // 提前5分钟检查续期(避免令牌刚过期时请求失败) if (DateTime.UtcNow.AddMinutes(5) >= expiresAt) { try { // 用刷新令牌获取新认证信息 var refreshedAuthLink = await authProvider.RefreshAuthAsync(refreshToken); // 更新会话中的令牌和过期时间 context.Session.SetString("_UserToken", refreshedAuthLink.FirebaseToken); context.Session.SetString("_RefreshToken", refreshedAuthLink.RefreshToken); var newExpiresAt = DateTime.UtcNow.AddSeconds(refreshedAuthLink.ExpiresIn); context.Session.SetString("_TokenExpiresAt", newExpiresAt.ToString("o")); } catch (Exception) { // 刷新令牌失效(如用户密码更改),跳转登录页 context.Response.Redirect("/Account/Login"); return; } } }
如果用中间件,在Program.cs中注册(需放在UseSession之后、UseRouting之前):
app.UseSession(); app.Use(async (context, next) => { var authProvider = new FirebaseAuthProvider(new FirebaseConfig("你的Firebase API Key")); await RefreshTokenIfNeeded(context, authProvider); await next(); }); app.UseRouting(); // 其他中间件...
二、延长ASP.NET Core会话时长
若需延长会话本身的闲置超时,在Program.cs中配置会话:
builder.Services.AddSession(options => { options.IdleTimeout = TimeSpan.FromHours(8); // 设置闲置8小时后过期 options.Cookie.HttpOnly = true; // 禁止前端JS访问,提升安全性 options.Cookie.IsEssential = true; // 标记为必要Cookie,符合合规要求 options.Cookie.SecurePolicy = CookieSecurePolicy.Always; // 生产环境启用,仅HTTPS传输 });
注意:必须确保app.UseSession()在app.UseRouting()和app.UseAuthorization()之前调用,否则会话无法正常工作。
三、进阶:用Cookie持久化刷新令牌
如果需要“记住我”这类长期登录功能,可将刷新令牌存储在HttpOnly Cookie中(而非会话):
// 登录时设置Cookie var cookieOptions = new CookieOptions { HttpOnly = true, Secure = true, Expires = DateTime.UtcNow.AddDays(7), // 7天过期 SameSite = SameSiteMode.Strict }; context.Response.Cookies.Append("FirebaseRefreshToken", refreshToken, cookieOptions); context.Response.Cookies.Append("FirebaseTokenExpiresAt", expiresAt.ToString("o"), cookieOptions);
续期时从Cookie读取刷新令牌,替换会话的读取逻辑即可。
内容的提问来源于stack exchange,提问作者Reed Kammerman
相关产品推荐
相关产品推荐

