如何在.NET Core 5 MVC中存取跨会话JWT Token Cookie实现记住登录功能
现有代码问题修正
你给出的AuthenticationProperties初始化代码存在明显语法错误:ExpiresUtc是DateTimeOffset?类型,不能直接赋值true,这个错误会导致Cookie持久化逻辑失效,你需要修正为匹配刷新令牌有效期的时间值,同时IsPersistent需要动态绑定用户“记住我”的勾选状态:
var authProperties = new AuthenticationProperties { AllowRefresh = true, // 与刷新令牌有效期保持一致 ExpiresUtc = DateTimeOffset.UtcNow.AddMonths(6), // 动态绑定前端传入的“记住我”勾选值,未勾选时为会话级Cookie IsPersistent = loginModel.RememberMe };
Login Get接口校验逻辑实现
这套自动刷新登录的逻辑不会默认自动执行,Cookie认证中间件只会验证Cookie本身的签名和有效期,不会自动调用你的外部身份接口刷新JWT,需要你手动在HttpGet类型的Login接口中实现,步骤如下:
- 给Login的Get方法添加
[AllowAnonymous]特性,避免未登录时被中间件直接拦截跳转 - 手动调用
HttpContext.AuthenticateAsync读取Cookie中存储的身份信息,哪怕JWT已过期也能拿到你存入的刷新令牌 - 调用认证接口执行刷新逻辑,刷新成功后重新写入Cookie直接跳转,失败则清除无效Cookie展示登录页
示例代码如下:
[HttpGet] [AllowAnonymous] public async Task<IActionResult> Login(string returnUrl = null) { // 已登录用户直接跳转 if (User.Identity.IsAuthenticated) { return Redirect(string.IsNullOrEmpty(returnUrl) ? Url.Action("Index", "Home") : returnUrl); } // 手动读取Cookie中的身份信息 var authResult = await HttpContext.AuthenticateAsync(CookieAuthenticationDefaults.AuthenticationScheme); if (authResult.Succeeded) { // 提取之前存入Claims的访问令牌和刷新令牌 var accessToken = authResult.Principal.FindFirstValue("AccessToken"); var refreshToken = authResult.Principal.FindFirstValue("RefreshToken"); // 调用你自己的身份验证API执行刷新 var refreshResp = await _yourAuthApi.RefreshToken(accessToken, refreshToken); if (refreshResp.IsSuccess) { // 刷新成功,重新构建身份写入Cookie var claims = new List<Claim> { new Claim("AccessToken", refreshResp.NewAccessToken), new Claim("RefreshToken", refreshResp.NewRefreshToken) // 其他你需要的用户声明 }; var claimsIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme); var newAuthProps = new AuthenticationProperties { AllowRefresh = true, ExpiresUtc = DateTimeOffset.UtcNow.AddMonths(6), // 复用原有持久化配置,保持记住我状态 IsPersistent = authResult.Properties.IsPersistent }; await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(claimsIdentity), newAuthProps); // 直接跳转目标地址,跳过登录流程 return Redirect(string.IsNullOrEmpty(returnUrl) ? Url.Action("Index", "Home") : returnUrl); } // 刷新失败,清除无效Cookie await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme); } ViewData["ReturnUrl"] = returnUrl; return View(); }
额外注意事项
- 刷新令牌必须做单次有效限制,每次刷新成功后立即废弃旧刷新令牌,下发新的刷新令牌,避免令牌被盗用后被长期滥用
- 你可以选择将刷新令牌单独存储在独立的HttpOnly加密Cookie中,不要存入Claims,进一步降低令牌泄露风险
- 确保Cookie配置开启了
HttpOnly、Secure(生产环境)属性,避免前端JS读取到Cookie内容
内容的提问来源于stack exchange,提问作者arc-menace
相关产品推荐
相关产品推荐

