一、需求剖析

如图所示,一般网站的登录界面都会有一个 [记住我] 按钮,当你勾选它登录后,即便你封闭浏览器再次翻开网站,也仍然会处于登录状况,无须重复验证暗码:

使用 Sa-Token 实现 [记住我] 模式登录、七天免登录

本文将详细介绍在 Sa-Token中,如何做到以下登录形式:

  • 记住我登录:登录后封闭浏览器,再次翻开网站登录状况仍然有用,无需重复登录。
  • 仅本次有用登录:登录后封闭浏览器,再次翻开网站登录状况将失效,需求再次登录。
  • 七天免登录:为登录状况设定一个详细的有用期,在这个期限内无需重复登录,过了期限后需求再次登录。

Sa-Token 是一个轻量级 java 权限认证结构,主要处理登录认证、权限认证、单点登录、OAuth2、微服务网关鉴权 等一系列权限相关问题。

Gitee 开源地址:gitee.com/dromara/sa-…

首先在项目中引进 Sa-Token 依赖:

<!-- Sa-Token 权限认证 -->
<dependency>
    <groupId>cn.dev33</groupId>
    <artifactId>sa-token-spring-boot-starter</artifactId>
    <version>1.34.0</version>
</dependency>

注:假如你运用的是 SpringBoot 3.x,只需求将 sa-token-spring-boot-starter 修改为 sa-token-spring-boot3-starter 即可。

二、在 Sa-Token 中完成记住我功用

Sa-Token的登录授权,默许便是[记住我]形式,为了完成[非记住我]形式,你需求在登录时如下设置:

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

那么,Sa-Token完成[记住我]的详细原理是?

三、完成原理

Cookie作为浏览器供给的默许会话跟踪机制,其生命周期有两种形式,分别是:

  • 暂时Cookie:有用期为本次会话,只需封闭浏览器窗口,Cookie就会消失。
  • 耐久Cookie:有用期为一个详细的时刻,在时刻未到期之前,即便用户封闭了浏览器Cookie也不会消失。

运用Cookie的此特性,咱们便能够轻松完成 [记住我] 形式:

  • 勾选 [记住我] 按钮时:调用StpUtil.login(10001, true),在浏览器写入一个耐久Cookie贮存 Token,此刻用户即便重启浏览器 Token 仍然有用。
  • 不勾选 [记住我] 按钮时:调用StpUtil.login(10001, false),在浏览器写入一个暂时Cookie贮存 Token,此刻用户在重启浏览器后 Token 便会消失,导致会话失效。

动态演示图:

使用 Sa-Token 实现 [记住我] 模式登录、七天免登录

四、前后端别离形式下如何完成[记住我]?

此刻机敏的你很快发现一个问题,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");

Remember me, it’s too easy!

五、登录时指定 Token 有用期

登录时不只能够指定是否为[记住我]形式,还能够指定一个特定的时刻作为 Token 有用时长,如下示例:

// 示例1:
// 指定token有用期(单位: 秒),如下所示token七天有用
StpUtil.login(10001, new SaLoginModel().setTimeout(60 * 60 * 24 * 7));
// ----------------------- 示例2:一切参数
// `SaLoginModel`为登录参数Model,其有诸多参数决定登录时的各种逻辑,例如:
StpUtil.login(10001, new SaLoginModel()
			.setDevice("PC")                 // 此次登录的客户端设备类型, 用于[同端互斥登录]时指定此次登录的设备类型
			.setIsLastingCookie(true)        // 是否为耐久Cookie(暂时Cookie在浏览器封闭时会主动删除,耐久Cookie在从头翻开后仍然存在)
			.setTimeout(60 * 60 * 24 * 7)    // 指定此次登录token的有用期, 单位:秒 (如未指定,主动取大局装备的 timeout 值)
			.setToken("xxxx-xxxx-xxxx-xxxx") // 预订此次登录的生成的Token 
			.setIsWriteHeader(false)         // 是否在登录后将 Token 写入到呼应头
			);

注:假如在登录时未指定 new SaLoginModel().setTimeout(604800) 那么结构将选用大局装备的 sa-token.timeout 值作为 Token 的有用期。

六、不同登录战略的代码对比

以下是三种登录战略的代码差异:

package com.pj.cases.up;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.util.SaResult;
/**
 * Sa-Token 记住我形式登录 
 * 
 * @author kong
 * @since 2022-10-17 
 */
@RestController
@RequestMapping("/RememberMe/")
public class RememberMeController {
	// 记住我登录    ---- http://localhost:8081/RememberMe/doLogin?name=zhang&pwd=123456
	@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?name=zhang&pwd=123456
	@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?name=zhang&pwd=123456
	@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("登录失利");
	}
}

可依次访问注释中供给的测验链接,调查不同登录战略带来的会话有用期差异。


参考资料

  • Sa-Token 文档:sa-token.cc
  • Gitee 仓库地址:gitee.com/dromara/sa-…
  • GitHub 仓库地址:github.com/dromara/sa-…