news 2026/9/13 12:46:34

Sa-Token 记住我(Remember Me)模式:原理、实现与前后端分离方案

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Sa-Token 记住我(Remember Me)模式:原理、实现与前后端分离方案

Sa-Token 记住我(Remember Me)模式:原理、实现与前后端分离方案

【免费下载链接】Sa-Token✨ 开源、免费、一站式 Java 权限认证框架,让鉴权变得简单、优雅!—— 登录认证、权限认证、分布式 Session 会话、微服务网关鉴权、SSO 单点登录、OAuth2.0 统一认证、jwt 集成、API Key 秘钥授权、API 参数签名项目地址: https://gitcode.com/GitHub_Trending/sa/Sa-Token

本文围绕 Sa-Token 的“[记住我] 模式”展开,讲解其背后的 Cookie 生命周期原理、StpUtil.login()的完整参数体系,以及 APP、小程序、PC 前后端分离环境下的等价实现方案。读完本文,你将掌握如何用一行代码控制登录后的浏览器会话存留,并为不同客户端定制 Token 有效期、持久 Cookie 与响应头写入等细节行为。

什么是 [记住我] 模式

大多数网站的登录界面都会提供一个[记住我]复选框:勾选它登录后,即使关闭浏览器再重新打开网站,用户依然处于登录状态,无须重新输入密码;不勾选时,一旦关闭浏览器,会话即随之失效。

其本质是浏览器Cookie 生命周期的两种形态:

  • 临时 Cookie:有效期仅限本次会话(浏览器进程),关闭浏览器窗口即被清除;
  • 持久 Cookie:有效期是一个具体的时间段,只要未到期,即使关闭浏览器 Cookie 也依然保留。

Sa-Token 正是利用这一特性,把 Token 的存留策略与“是否记住我”绑定:勾选时写入持久 Cookie,不勾选时写入临时 Cookie。

在 Sa-Token 中实现:默认就是 [记住我]

Sa-Token 的登录授权默认就是[记住我]模式。因此,如果要实现“非记住我”(关闭浏览器后需重新登录),只需要在登录时显式传入false

// 设置登录账号id为10001,第二个参数指定是否为[记住我] // 当此值为 false 后,关闭浏览器再次打开需要重新登录 StpUtil.login(10001, false);

该重载在 StpUtil.java 中定义,isLastingCookietrue时即“记住我”,false时关闭浏览器需重新登录。从源码可以推断,它最终等价于:

StpUtil.login(10001, new SaLoginParameter().setIsLastingCookie(false));

仓库内 sa-token-demo-case 提供了可直接运行对照的示例接口:

// 记住我登录 ---- http://localhost:8081/RememberMe/doLogin?name=zhang&pwd=123456 StpUtil.login(10001, true); // 不记住我登录 ---- http://localhost:8081/RememberMe/doLogin2?name=zhang&pwd=123456 StpUtil.login(10001, false);

实现原理:Token 写入 Cookie 的底层机制

登录后,Sa-Token 会把 Token 写入当前会话的 Cookie,核心逻辑位于 StpLogic.java 的setTokenValueToCookie()方法:

SaCookie cookie = new SaCookie() .setName(getTokenName()) .setValue(tokenValue) .setMaxAge(cookieTimeout) // Cookie 存活时间(单位:秒) ... SaHolder.getResponse().addCookie(cookie);

关键在于cookieTimeout的取值,它由 SaLoginParameter.getCookieTimeout() 计算得出:

public int getCookieTimeout() { if (!Boolean.TRUE.equals(getIsLastingCookie())) { return -1; // 非持久 Cookie:-1,浏览器关闭即失效 } long _timeout = getTimeout(); if (_timeout == SaTokenDao.NEVER_EXPIRE || _timeout > Integer.MAX_VALUE) { return Integer.MAX_VALUE; // 永不过期或超大值,取 Integer 上限 } return (int)_timeout; // 持久 Cookie:存活时间 = Token 有效期 }

于是两种模式在浏览器侧表现为:

登录方式写入的 CookieCookie Max-Age关闭浏览器后
StpUtil.login(10001, true)持久 Cookie等于 Token 有效期(秒)Token 仍保留,无需重新登录
StpUtil.login(10001, false)临时 Cookie-1(内存 Cookie)Token 随浏览器进程消失,会话失效

这也解释了为什么“不记住我”模式下,服务端 Token 数据其实并未立即删除——只是浏览器丢失了 Token 凭据,下次无法再携带它发起认证。

全局配置:isLastingCookie 默认值为 true

“默认就是记住我”的根源在于全局配置。在 SaTokenConfig.java 中:

/** * 是否为持久Cookie(临时Cookie在浏览器关闭时会自动删除,持久Cookie在重新打开后依然存在) */ private Boolean isLastingCookie = true;

如果希望整个项目默认走“非记住我”,可以在配置文件中将sa-token.is-lasting-cookie设为false,随后未显式指定该参数的login()调用都会自动使用非持久 Cookie。

前后端分离:Cookie 失效了怎么办?

一个自然的疑问是:Cookie 方案依赖浏览器会话机制,那在APP、小程序等前后端分离环境下是否无效?

答案是肯定的——任何基于 Cookie 的认证方案在前后端分离环境下都会失效,因为这些客户端默认没有实现 Cookie 功能。不过,它们通常都提供了替代的本地存储机制,代价是Token 的生命周期需要由前端手动控制

以经典跨端框架uni-app为例:

// 使用本地存储保存 token,达到 [持久Cookie] 的效果 uni.setStorageSync("satoken", "xxxx-xxxx-xxxx-xxxx-xxx"); // 使用 globalData 保存 token,达到 [临时Cookie] 的效果 getApp().globalData.satoken = "xxxx-xxxx-xxxx-xxxx-xxx";

若在PC 浏览器环境下进行前后端分离开发,则更加简单:

// 使用 localStorage 保存 token,达到 [持久Cookie] 的效果 localStorage.setItem("satoken", "xxxx-xxxx-xxxx-xxxx-xxx"); // 使用 sessionStorage 保存 token,达到 [临时Cookie] 的效果 sessionStorage.setItem("satoken", "xxxx-xxxx-xxxx-xxxx-xxx");

提示:localStorage的数据不会随标签页/窗口关闭而清除,对应“记住我”;sessionStorage的生命周期与浏览器会话绑定,对应“非记住我”。仓库中 sa-token-demo-remember-me 提供了一个完整的 Vue3 + Vite 前端工程 + Spring Boot 后端的“记住我”演示:后端 UserLoginController.java 通过StpUtil.login(10001, remember)接收前端复选框状态,前端工程在page_project/目录下,可参考其登录、状态校验与注销的完整交互。

登录时指定 Token 有效期

“记住我”只是二选一的开关,实践中往往还需要精确控制 Token 的有效时长。登录时可以用SaLoginParameter指定一个具体时间(单位:秒):

// 示例1:指定 token 有效期(单位:秒),如下所示 token 七天有效 StpUtil.login(10001, new SaLoginParameter().setTimeout(60 * 60 * 24 * 7));

当传入timeout后,持久 Cookie 的 Max-Age 也会同步等于该时长(见上文getCookieTimeout()逻辑),即“记住我 + 七天有效”。

对应地,StpUtil.login(Object id, long timeout)这个便捷重载可直接使用:

// 七天免登录 ---- http://localhost:8081/RememberMe/doLogin3?name=zhang&pwd=123456 StpUtil.login(10001, 60 * 60 * 24 * 7);

上述接口均可在 RememberMeController.java 中看到完整上下文。

SaLoginParameter:登录参数的完整清单

SaLoginParameter是登录时的参数 Model,除“记住我”与有效期外,还决定登录过程中的各种行为。该类的全部字段与含义定义于 SaLoginParameter.java,核心参数整理如下:

参数含义备注/默认来源
deviceType此次登录的客户端设备类型用于[同端互斥登录]时指定设备端,默认取全局配置
deviceId此次登录的客户端设备 id用于设备维度会话管理
timeout此次登录 token 有效期(秒)未指定时自动取全局timeout
activeTimeout此次登录 token 最低活跃频率(秒)未指定时使用全局activeTimeout
isConcurrent是否允许同一账号多地同时登录true一起登录,false新登录挤掉旧登录
isShare多人登录同一账号时是否共用一个 tokentrue共用,false每次新建
maxLoginCount同一账号最大登录数量-1不限,仅在isConcurrent=true, isShare=false时有意义
maxTryTimes创建 token 时的最高循环尝试次数用于保证 token 唯一性,-1不循环直接使用
isLastingCookie是否为持久 Cookietrue记住我,false临时 Cookie
isWriteHeader是否在登录后将 Token 写入响应头前后端分离场景常用
token预定本次登录生成的 Token 值需自行保证唯一性
rightNowCreateTokenSession登录时是否立即创建 Token-Sessiontrue立即创建,false首次调用getTokenSession()时创建
replacedLoginExitMode/replacedRange顶人下线时的策略与范围isConcurrent=false时生效
overflowLogoutMode溢出maxLoginCount时的下线方式LOGOUT注销 /KICKOUT踢人 /REPLACED顶人
extraData扩展信息只在 jwt 模式下生效
cookieCookie 配置对象可单独覆盖 domain、path、secure、httpOnly、sameSite 等

一个覆盖主要参数的完整示例:

StpUtil.login(10001, new SaLoginParameter() .setDeviceType("PC") // 此次登录的客户端设备类型,用于[同端互斥登录]时指定此次登录的设备类型 .setIsLastingCookie(true) // 是否为持久Cookie(临时Cookie在浏览器关闭时会自动删除,持久Cookie在重新打开后依然存在) .setTimeout(60 * 60 * 24 * 7) // 指定此次登录token的有效期,单位:秒(如未指定,自动取全局配置的 timeout 值) .setToken("xxxx-xxxx-xxxx-xxxx") // 预定此次登录生成的Token .setIsWriteHeader(false) // 是否在登录后将 Token 写入到响应头 );

从源码结构看,SaLoginParameter的构造器会调用setDefaultValues(SaManager.getConfig()),将全局配置一次性填充为默认值(SaLoginParameter.java),因此你只需显式设置需要覆盖的字段,未指定的行为自动跟随全局配置,这正是“按次登录精细控制、不污染全局”的设计思路。

实践建议与注意事项

  • 区分两层过期:服务端 Token 过期时间与浏览器 Cookie 存活时间并非同一概念。持久 Cookie 只是让 Token 凭据“不丢”,真正限制登录状态的是 Token 有效期;非持久 Cookie 则是“凭据丢失”导致被动下线。理解这一点有助于排查“明明没过期却掉线”的问题。
  • 前后端分离时前端负责“存”:由于不依赖 Cookie,Token 的持久与否由前端存储方案(localStorage / sessionStorage / 小程序本地存储)决定,服务端只需保证 Token 本身的有效期配置正确。
  • 响应头透传:在 APP 等场景可将isWriteHeader设为true,登录后从响应头读取 Token,再由前端按需求自行存储,这与 SaTokenConfig 中isReadHeaderisReadCookie的读写配置相互配合,构成完整的双端 Token 传递闭环。
  • 安全提示:为持久 Cookie 设置合理的有效期(而非永不过期),并配合 Token 活跃频率(activeTimeout)实现“长时间无操作自动失效”,可在便利性与安全性之间取得平衡。

至此,从“勾选记住我”到“指定七天有效期”,再到前后端分离环境下的存储策略,Sa-Token 的会话存留机制已全部打通——正如官方文档所言:Remember me, it's too easy!

【免费下载链接】Sa-Token✨ 开源、免费、一站式 Java 权限认证框架,让鉴权变得简单、优雅!—— 登录认证、权限认证、分布式 Session 会话、微服务网关鉴权、SSO 单点登录、OAuth2.0 统一认证、jwt 集成、API Key 秘钥授权、API 参数签名项目地址: https://gitcode.com/GitHub_Trending/sa/Sa-Token

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/13 12:44:38

EKF-SLAM可观测性分析与不一致性改进研究

1. 项目概述:EKF-SLAM中的可观测性与不一致性问题研究在机器人自主导航领域,基于扩展卡尔曼滤波器(EKF)的同时定位与地图构建(SLAM)算法一直是经典解决方案。然而,实际应用中经常遇到状态估计不一致的问题,这直接影响了SLAM系统的…

作者头像 李华
网站建设 2026/9/13 12:43:26

InsForge 密钥管理:4 步配好 .env,让配置直接过上线自查

InsForge 密钥管理:4 步配好 .env,让配置直接过上线自查 【免费下载链接】InsForge The all-in-one, open-source backend platform for agentic coding. InsForge gives your coding agent database, auth, storage, compute, hosting, and AI gateway …

作者头像 李华
网站建设 2026/9/13 12:42:15

智能小区电动汽车充电博弈定价策略与MATLAB实现

1. 项目背景与核心挑战智能小区中的电动汽车充电管理正面临着一个典型的两难困境:电力代理商希望最大化售电收益,而车主则追求充电成本最小化。这种利益冲突在传统定价模式下往往导致供需失衡——要么电价过高抑制需求,要么低价策略让代理商无…

作者头像 李华
网站建设 2026/9/13 12:42:11

grbl v1.1运动控制内核全解析:从G代码到步进脉冲

简介:这是一份基于grbl v1.1的完整开源源码包,面向桌面级CNC雕刻机与3D打印机的嵌入式开发者、硬件爱好者和二次开发人员,用于在Arduino平台上实现高效率、低成本的G代码解释与运动控制。压缩包共69个文件,以C语言源码&#xff08…

作者头像 李华