ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

Sa-Token「记住我」模式全解析:临时 Cookie、持久 Cookie 与登录参数定制实战

Sa-Token「记住我」模式全解析:临时 Cookie、持久 Cookie 与登录参数定制实战 Sa-Token「记住我」模式全解析临时 Cookie、持久 Cookie 与登录参数定制实战【免费下载链接】Sa-Token✨ 开源、免费、一站式 Java 权限认证框架让鉴权变得简单、优雅—— 登录认证、权限认证、分布式 Session 会话、微服务网关鉴权、SSO 单点登录、OAuth2.0 统一认证、jwt 集成、API Key 秘钥授权、API 参数签名项目地址: https://gitcode.com/GitHub_Trending/sa/Sa-Token几乎所有网站登录界面上都有一个「记住我」复选框勾选后即使关闭浏览器再重新打开依旧保持登录状态无需重复输入密码。本篇文章聚焦 Sa-Token 框架中「记住我」模式的完整实现从默认行为、两种 Cookie 生命周期的底层原理到前后端分离环境APP、小程序、PC 浏览器下的替代方案再到利用SaLoginParameter精细控制 Token 有效期与登录细节。读完本文你将掌握用一条login()调用精确掌控会话寿命的完整实战能力。一、Sa-Token 中的「记住我」默认就是开启的在 Sa-Token 中「记住我」并不是一个需要额外开启的功能恰恰相反——Sa-Token 的登录授权默认就是「记住我」模式。也就是说日常最常见的这种写法StpUtil.login(10001);等价于「勾选了记住我」的登录登录成功后框架会在浏览器写入一个持久 Cookie用户关闭浏览器再打开会话依然有效。这一点在源码中有明确依据SaTokenConfig.java 中isLastingCookie字段的默认值为true同时默认timeoutToken 有效期为60 * 60 * 24 * 30即 30 天同文件第 47 行。而要实现「非记住我」模式只需在登录时显式传入第二个参数// 设置登录账号id为10001第二个参数指定是否为[记住我] // 当此值为 false 后关闭浏览器后再次打开需要重新登录 StpUtil.login(10001, false);二、实现原理临时 Cookie 与持久 CookieSa-Token 之所以能用一行代码切换「记住我」与「非记住我」靠的是 Cookie 作为浏览器会话跟踪机制的两种生命周期形式临时 Cookie有效期为本次会话只要关闭浏览器窗口Cookie 就会消失。持久 Cookie有效期为一个具体的时间段在时间未到期之前即使用户关闭浏览器Cookie 也不会消失。利用这一特性「记住我」的实现逻辑非常直观用户操作框架调用写入浏览器的 Cookie重启浏览器后的效果勾选「记住我」StpUtil.login(10001, true)持久 Cookie 储存 TokenToken 依然有效保持登录不勾选「记住我」StpUtil.login(10001, false)临时 Cookie 储存 TokenToken 随之消失会话失效源码级佐证Cookie 的存活时长是如何计算的从源码看登录后的 Token 注入流程位于 StpLogic.java 的setTokenValue(tokenValue, loginParameter)方法框架会将 Token 依次写入 Storage 存储器、浏览器 Cookie并在需要时写入响应头。其中写入 Cookie 时使用的存活时长由 SaLoginParameter.java 中的getCookieTimeout()方法计算public int getCookieTimeout() { // 非持久 Cookie返回 -1代表内存级 Cookie浏览器关闭即消失 if (!Boolean.TRUE.equals(getIsLastingCookie())) { return -1; } long _timeout getTimeout(); // 持久 Cookie直接使用 Token 的有效期作为 Cookie 存活时长 if(_timeout SaTokenDao.NEVER_EXPIRE || _timeout Integer.MAX_VALUE) { return Integer.MAX_VALUE; } return (int)_timeout; }可以看到核心规律isLastingCookie false时Cookie 的Max-Age被设为-1即会话级临时Cookie浏览器关闭即清除isLastingCookie true时Cookie 的存活时长与 Token 有效期保持一致若 Token 设为永久有效-1或超出int上限Cookie 存活时长取Integer.MAX_VALUE。最终这个值通过new SaCookie().setMaxAge(cookieTimeout)写入 Cookie见 StpLogic.java。值得注意的是Token 本体在服务端存储的有效期与 Cookie 存活时长是两套独立的机制持久 Cookie 只是让浏览器“留着这张令牌”令牌在服务端是否过期仍由timeout决定。因此更安全的实践是让 Cookie 存活时长 ≤ Token 服务端有效期Sa-Token 默认的策略正是二者保持一致。三、登录时的四种重载写法StpLogic提供了多种登录重载方便在不同场景下快速指定登录细节对应静态方法见 StpUtil.java// 1. 默认登录使用全局配置默认即“记住我”有效期 30 天 StpUtil.login(10001); // 2. 指定设备类型用于同端互斥登录等场景 StpUtil.login(10001, PC); // 3. 指定是否为“记住我” StpUtil.login(10001, true); // 持久 Cookie StpUtil.login(10001, false); // 临时 Cookie关浏览器即失效 // 4. 指定 Token 有效期单位秒7 天有效 StpUtil.login(10001, 60 * 60 * 24 * 7);从 StpLogic.java 的实现可以看到这些重载最终都会汇聚到login(id, SaLoginParameter)先把id与参数对象传入createLoginSession()创建会话再把生成的 Token 注入当前客户端Storage Cookie 可选响应头也就是说登录行为的所有细节都由SaLoginParameter这一个参数模型统一承载。四、登录时指定 Token 有效期除了指定是否「记住我」你还可以在登录时指定一个精确的 Token 有效时长// 指定 token 有效期单位秒如下所示 token 七天有效 StpUtil.login(10001, new SaLoginParameter().setTimeout(60 * 60 * 24 * 7));这里的SaLoginParameter会以全局配置为默认值见 SaLoginParameter.java 的setDefaultValues方法你只需覆盖关心的字段即可未指定的项自动沿用 SaTokenConfig 中的全局配置。SaLoginParameter 全参数速查SaLoginParameter是登录参数的完整 Model覆盖了登录时的各种细节逻辑常用参数如下StpUtil.login(10001, new SaLoginParameter() .setDeviceType(PC) // 此次登录的客户端设备类型用于[同端互斥登录]时指定此次登录的设备类型 .setIsLastingCookie(true) // 是否为持久Cookie临时Cookie在浏览器关闭时会自动删除持久Cookie在重新打开后依然存在 .setTimeout(60 * 60 * 24 * 7) // 指定此次登录token的有效期, 单位:秒如未指定自动取全局配置的 timeout 值 .setActiveTimeout(60 * 60) // 指定此次登录token的最低活跃频率, 单位:秒如未指定则使用全局配置的 activeTimeout 值 .setToken(xxxx-xxxx-xxxx-xxxx) // 预定此次登录生成的Token .setIsWriteHeader(false) // 是否在登录后将 Token 写入到响应头 .setIsConcurrent(true) // 是否允许同一账号多地同时登录false 时新登录挤掉旧登录 .setIsShare(true) // 多人登录同一账号时是否共用一个 token .setMaxLoginCount(-1) // 同一账号最大登录数量-1 代表不限 );各字段含义与取值说明依据 SaLoginParameter.java 源码注释参数类型说明deviceTypeString客户端设备类型默认DEFAULT_LOGIN_DEVICE_TYPE用于同端互斥登录deviceIdString客户端设备 idtimeoutlongToken 有效期秒未指定取全局timeout默认 30 天-1永久有效activeTimeoutLongToken 最低活跃频率秒超过该时间未访问系统会被冻结默认-1不限制isConcurrentBoolean是否允许同一账号多地同时登录false时新登录挤掉旧登录isShareBoolean多人登录同一账号时是否共用同一个 tokenmaxLoginCountint同一账号最大登录数量-1不限仅在isConcurrenttrue, isSharefalse时生效maxTryTimesint创建 token 时的最高循环次数用于保证唯一性-1不循环尝试isLastingCookieBoolean是否为持久 Cookie即「记住我」开关isWriteHeaderBoolean是否在登录后将 Token 写入响应头tokenString预定本次登录生成的 Token 值extraDataMap扩展信息仅在 JWT 模式下生效可用setExtra(key, value)写入rightNowCreateTokenSessionBoolean登录时是否立即创建 Token-SessioncookieSaCookieConfig本次登录的 Cookie 配置对象domain、path、secure、httpOnly、sameSite 等可通过setupCookieConfig(...)定制写入响应头的注意事项当isWriteHeader为true时框架会把 Token 写入当前请求的响应头。从 StpLogic.java 的setTokenValueToResponseHeader()可以看到框架除了写入 Token 本身还会同时写入Access-Control-Expose-Headers响应头——否则跨域场景下前端 JS 将无法读取到该自定义响应头。这一细节在前后端分离开发时需要留意。五、前后端分离模式下如何实现「记住我」Cookie 虽好却无法在前后端分离环境下使用——APP、小程序等客户端默认没有实现 Cookie 功能因此任何基于 Cookie 的认证方案在纯前后端分离架构下都会失效。好在这些客户端一般都提供了本地存储方案我们可以用「前端手动控制 Token 生命周期」的方式达到同样的效果核心思路是用本地持久存储模拟「持久 Cookie」、用会话级内存存储模拟「临时 Cookie」。跨端框架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);在这种模式下前端的职责是登录接口返回 Token 后根据用户是否勾选「记住我」选择对应的存储介质保存之后每次请求拦截器/axios 请求头携带该 Token 供服务端校验退出登录或 Token 过期时再将其清除。后端则通过 Sa-Token 的 Token 读取机制从请求头或参数中获取凭证完成鉴权。六、完整可运行的 DemoRememberMeController为了便于直接上手验证仓库在sa-token-demo-case模块中提供了一个完整的控制器示例RememberMeController.java其中包含三种典型登录场景RestController RequestMapping(/RememberMe/) public class RememberMeController { // 记住我登录 ---- http://localhost:8081/RememberMe/doLogin?namezhangpwd123456 RequestMapping(doLogin) public SaResult doLogin(String name, String pwd) { if(zhang.equals(name) 123456.equals(pwd)) { StpUtil.login(10001, true); return SaResult.ok(登录成功); } return SaResult.error(登录失败); } // 不记住我登录 ---- http://localhost:8081/RememberMe/doLogin2?namezhangpwd123456 RequestMapping(doLogin2) public SaResult doLogin2(String name, String pwd) { if(zhang.equals(name) 123456.equals(pwd)) { StpUtil.login(10001, false); return SaResult.ok(登录成功); } return SaResult.error(登录失败); } // 七天免登录 ---- http://localhost:8081/RememberMe/doLogin3?namezhangpwd123456 RequestMapping(doLogin3) public SaResult doLogin3(String name, String pwd) { if(zhang.equals(name) 123456.equals(pwd)) { StpUtil.login(10001, 60 * 60 * 24 * 7); return SaResult.ok(登录成功); } return SaResult.error(登录失败); } }三个接口分别演示了「记住我登录」「不记住我登录」「指定 7 天有效期登录」启动该模块后可直接通过浏览器访问对应 URL 验证效果是理解本文全部内容的最佳实践入口。七、小结与选型建议「记住我」功能在 Sa-Token 中实现成本极低关键在于理解它的两层设计Cookie 层面isLastingCookie决定写入持久 Cookie 还是临时 Cookie控制“浏览器关闭后 Token 是否还在”服务端层面timeout决定 Token 在服务端存储的有效期控制“令牌本身何时过期”。建议按业务场景选择默认登录直接StpUtil.login(id)即持久 Cookie 30 天有效期适合对会话时长要求宽松的场景敏感操作StpUtil.login(id, false)临时 Cookie关闭浏览器即失效适合涉及资金、隐私等敏感功能精细化控制通过SaLoginParameter组合isLastingCookie、timeout、activeTimeout、isConcurrent等参数按接口粒度定制每一次登录行为前后端分离放弃 Cookie 方案前端根据「记住我」勾选状态选择 localStorage / sessionStorage 保存 Token配合响应头或请求参数传递凭证。相关参考RememberMeController 示例、SaLoginParameter 参数模型、StpLogic 登录实现、SaTokenConfig 全局配置。【免费下载链接】Sa-Token✨ 开源、免费、一站式 Java 权限认证框架让鉴权变得简单、优雅—— 登录认证、权限认证、分布式 Session 会话、微服务网关鉴权、SSO 单点登录、OAuth2.0 统一认证、jwt 集成、API Key 秘钥授权、API 参数签名项目地址: https://gitcode.com/GitHub_Trending/sa/Sa-Token创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表