如何在Duende Identity Server中实现持久化登录的「记住我」功能?
你的问题核心在于Duende Identity Server生成的idsrv.session Cookie是会话级,而非持久化Cookie,这和.AspNetCore.Identity.Application Cookie的设置无关。要实现「记住我」持久化,需要从以下几个关键点调整:
1. 配置Duende Identity Server生成持久化会话Cookie
在Identity Server的启动配置(Program.cs/Startup.cs)中,针对idsrv.session Cookie设置持久化规则,同时关联前端传递的「记住我」参数:
调整Cookie认证选项,设置默认有效期和滑动过期:
services.AddAuthentication() .AddCookie("idsrv.session", options => { options.Cookie.Name = "idsrv.session"; options.ExpireTimeSpan = TimeSpan.FromDays(30); // 设置持久化有效期 options.SlidingExpiration = true; // 用户活动时自动刷新有效期 options.Cookie.SecurePolicy = CookieSecurePolicy.Always; // 生产环境必须开启 options.Cookie.SameSite = SameSiteMode.Lax; // 根据跨域场景调整 });在登录逻辑中(比如使用ASP.NET Core Identity的
SignInManager),根据前端传递的rememberMe参数设置会话持久化:[HttpPost] public async Task<IActionResult> Login(LoginViewModel model) { // 用户验证逻辑... var result = await _signInManager.PasswordSignInAsync(model.Username, model.Password, model.RememberMe, lockoutOnFailure: false); if (result.Succeeded) { return RedirectToAction("Index", "Home"); } // 错误处理... }这里的
model.RememberMe对应前端传递的参数,PasswordSignInAsync的第三个参数用于控制是否生成持久化会话Cookie。
2. 前端oidc-client-ts传递「记住我」参数
调用登录方法时,通过extraQueryParams把rememberMe参数传给Identity Server:
const userManager = new UserManager({ authority: "https://your-identity-server-url", client_id: "your-client-id", redirect_uri: "https://your-app/callback", response_type: "code", scope: "openid profile your-api-scope", automaticSilentRenew: true // 开启自动静默刷新 }); // 登录时传递rememberMe参数 userManager.signinRedirect({ extraQueryParams: { rememberMe: true } });
3. 让oidc-client-ts持久化存储刷新令牌
默认情况下,oidc-client-ts会把用户状态(包括刷新令牌)存在sessionStorage里,关闭浏览器就会丢失。需要改成localStorage实现持久化:
const userManager = new UserManager({ // 其他配置... store: new WebStorageStateStore({ store: window.localStorage }) // 改用localStorage存储状态 });
这样关闭浏览器后再次打开页面,userManager能从localStorage读取状态,自动触发静默刷新获取新的访问令牌,无需用户重新登录。
4. 验证Cookie的持久化属性
登录后,在浏览器开发者工具的「Application」->「Cookies」中查看idsrv.session:
- 确认
Expires/Max-Age不是「Session」,而是你设置的有效期(比如30天后) - 确认
Secure和SameSite属性符合部署环境要求(跨域场景可能需要设置SameSite=None并开启Secure)
内容的提问来源于stack exchange,提问作者bjorkblom

