今天最近在做登录、授权的功能,一开始考虑到的是spring boot + spring security
,但spring security
太重,而我们是轻量级的项目,所以,spring security
不适合我们。
而后考虑spring boot + shiro
,但shiro
自带的aop
会影响spring boot
的aop
,所以,shiro
也不适合我们。
后来浏览github
时,发现Sa-Token
这个框架,如下是Sa-Token
的功能图:
该框架的stars
如下:
Gitee
(码云)上的stars
github
上的stars
接下来,我们便详细分析Sa-Token
这个框架。
Sa-Token
是一个轻量级Java
权限认证框架。
主要解决的问题如下:
登录认证
权限认证
单点登录
OAuth2.0
分布式Session会话
微服务网关鉴权等一系列权限相关问题。
对于一些登录之后才能访问的接口(例如:查询我的账号资料),我们通常的做法是增加一层接口校验:
如果校验通过,则:正常返回数据。
如果校验未通过,则:抛出异常,告知其需要先进行登录。
那么,判断会话是否登录的依据是什么?我们先来简单分析一下登录访问流程:
用户提交name + password
参数,调用登录接口。
登录成功,返回这个用户的Token
会话凭证。
用户后续的每次请求,都携带上这个Token
。
服务器根据Token
判断此会话是否登录成功。
所谓登录认证,指的就是服务器校验账号密码,为用户颁发Token
会话凭证的过程,这个Token
也是我们后续通过接口校验的关键所在。
根据以上思路,我们需要一个会话登录的函数:
// 会话登录:参数填写要登录的账号id,建议的数据类型:long | int | String, 不可以传入复杂类型,如:User、Admin 等等
StpUtil.login(Object id);
只此一句代码,便可以使会话登录成功,实际上Sa-Token
在背后做了大量的工作,包括但不限于:
检查此账号是否已被封禁
检查此账号是否之前已有登录
为账号生成 Token 凭证与 Session 会话
通知全局侦听器,xx 账号登录成功
将 Token 注入到请求上下文
等等其它工作……
你暂时不需要完整的了解整个登录过程,你只需要记住关键一点:Sa-Token
为这个账号创建了一个Token
凭证,且通过Cookie
上下文返回给了前端。
所以一般情况下,我们的登录接口代码,会大致类似如下:
// 会话登录接口
@RequestMapping("doLogin")
public SaResult doLogin(String name, String pwd) {
// 第一步:比对前端提交的账号名称、密码
if("zhang".equals(name) && "123456".equals(pwd)) {
// 第二步:根据账号id,进行登录
StpUtil.login(10001);
return SaResult.ok("登录成功");
}
return SaResult.error("登录失败");
}
如果你对以上代码阅读没有压力,你可能会注意到略显奇怪的一点:此处仅仅做了会话登录,但并没有主动向前端返回Token
信息。 是因为不需要吗?严格来讲是需要的,只不过StpUtil.login(id)
方法利用了Cookie
自动注入的特性,省略了你手写返回Token
的代码。
你需要了解Cookie
最基本的两点:
Cookie
可以从后端控制往浏览器中写入Token
值。
Cookie
会在每次请求时自动提交Token
值。
因此,在Cookie
功能的加持下,我们可以仅靠StpUtil.login(id)
一句代码就完成登录认证。
除了登录方法,我们还需要:
// 当前会话注销登录
StpUtil.logout();
// 获取当前会话是否已经登录,返回true=已登录,false=未登录
StpUtil.isLogin();
// 检验当前会话是否已经登录, 如果未登录,则抛出异常:`NotLoginException`
StpUtil.checkLogin();
异常NotLoginException
代表当前会话暂未登录,可能的原因有很多:
前端没有提交 Token
前端提交的 Token 是无效的
前端提交的 Token 已经过期
…… 等等
// 获取当前会话账号id, 如果未登录,则抛出异常:`NotLoginException`
StpUtil.getLoginId();
// 类似查询API还有:
StpUtil.getLoginIdAsString(); // 获取当前会话账号id, 并转化为`String`类型
StpUtil.getLoginIdAsInt(); // 获取当前会话账号id, 并转化为`int`类型
StpUtil.getLoginIdAsLong(); // 获取当前会话账号id, 并转化为`long`类型
// ---------- 指定未登录情形下返回的默认值 ----------
// 获取当前会话账号id, 如果未登录,则返回null
StpUtil.getLoginIdDefaultNull();
// 获取当前会话账号id, 如果未登录,则返回默认值 (`defaultValue`可以为任意类型)
StpUtil.getLoginId(T defaultValue);
Token
查询// 获取当前会话的token值
StpUtil.getTokenValue();
// 获取当前`StpLogic`的token名称
StpUtil.getTokenName();
// 获取指定token对应的账号id,如果未登录,则返回 null
StpUtil.getLoginIdByToken(String tokenValue);
// 获取当前会话剩余有效期(单位:s,返回-1代表永久有效)
StpUtil.getTokenTimeout();
// 获取当前会话的token信息参数
StpUtil.getTokenInfo();
有关TokenInfo
参数详解,如下代码所示:
{
"code": 200,
"msg": "ok",
"data": {
"tokenName": "satoken", // token名称
"tokenValue": "e67b99f1-3d7a-4a8d-bb2f-e888a0805633", // token值
"isLogin": true, // 此token是否已经登录
"loginId": "10001", // 此token对应的LoginId,未登录时为null
"loginType": "login", // 账号类型标识
"tokenTimeout": 2591977, // token剩余有效期 (单位: 秒)
"sessionTimeout": 2591977, // User-Session剩余有效时间 (单位: 秒)
"tokenSessionTimeout": -2, // Token-Session剩余有效时间 (单位: 秒)
"tokenActivityTimeout": -1, // token剩余无操作有效时间 (单位: 秒)
"loginDevice": "default-device" // 登录设备类型
},
}
新建LoginController
,复制以下代码
/**
* 登录测试
*/
@RestController
@RequestMapping("/acc/")
public class LoginController {
// 测试登录 ---- http://localhost:8081/acc/doLogin?name=zhang&pwd=123456
@RequestMapping("doLogin")
public SaResult doLogin(String name, String pwd) {
// 此处仅作模拟示例,真实项目需要从数据库中查询数据进行比对
if("zhang".equals(name) && "123456".equals(pwd)) {
StpUtil.login(10001);
return SaResult.ok("登录成功");
}
return SaResult.error("登录失败");
}
// 查询登录状态 ---- http://localhost:8081/acc/isLogin
@RequestMapping("isLogin")
public SaResult isLogin() {
return SaResult.ok("是否登录:" + StpUtil.isLogin());
}
// 查询 Token 信息 ---- http://localhost:8081/acc/tokenInfo
@RequestMapping("tokenInfo")
public SaResult tokenInfo() {
return SaResult.data(StpUtil.getTokenInfo());
}
// 测试注销 ---- http://localhost:8081/acc/logout
@RequestMapping("logout")
public SaResult logout() {
StpUtil.logout();
return SaResult.ok();
}
}
所谓权限认证,核心逻辑就是判断一个账号是否拥有指定权限:
有,就让你通过。
没有?那么禁止访问!
深入到底层数据中,就是每个账号都会拥有一个权限码集合,框架来校验这个集合中是否包含指定的权限码。
例如:当前账号拥有权限码集合 [user-add
, user-delete
, user-get
],这时候我来校验权限 user-update
,则其结果就是:验证失败,禁止访问。
所以现在问题的核心就是:
因为每个项目的需求不同,其权限设计也千变万化,因此 [ 获取当前账号权限码集合 ] 这一操作不可能内置到框架中, 所以Sa-Token
将此操作以接口的方式暴露给你,以方便你根据自己的业务逻辑进行重写。
你需要做的就是新建一个类,实现StpInterface
接口,例如以下代码:
/**
* 自定义权限验证接口扩展
*/
@Component // 保证此类被SpringBoot扫描,完成Sa-Token的自定义权限验证扩展
public class StpInterfaceImpl implements StpInterface {
/**
* 返回一个账号所拥有的权限码集合
*/
@Override
public List<String> getPermissionList(Object loginId, String loginType) {
// 本list仅做模拟,实际项目中要根据具体业务逻辑来查询权限
List<String> list = new ArrayList<String>();
list.add("101");
list.add("user-add");
list.add("user-delete");
list.add("user-update");
list.add("user-get");
list.add("article-get");
return list;
}
/**
* 返回一个账号所拥有的角色标识集合 (权限与角色可分开校验)
*/
@Override
public List<String> getRoleList(Object loginId, String loginType) {
// 本list仅做模拟,实际项目中要根据具体业务逻辑来查询角色
List<String> list = new ArrayList<String>();
list.add("admin");
list.add("super-admin");
return list;
}
}
参数解释:
loginId
:账号id,即你在调用StpUtil.login(id)
时写入的标识值。loginType
:账号体系标识然后就可以用以下api来鉴权了
// 获取:当前账号所拥有的权限集合
StpUtil.getPermissionList();
// 判断:当前账号是否含有指定权限, 返回true或false
StpUtil.hasPermission("user-update");
// 校验:当前账号是否含有指定权限, 如果验证未通过,则抛出异常: NotPermissionException
StpUtil.checkPermission("user-update");
// 校验:当前账号是否含有指定权限 [指定多个,必须全部验证通过]
StpUtil.checkPermissionAnd("user-update", "user-delete");
// 校验:当前账号是否含有指定权限 [指定多个,只要其一验证通过即可]
StpUtil.checkPermissionOr("user-update", "user-delete");
扩展:NotPermissionException
对象可通过getLoginType()
方法获取具体是哪个StpLogic
抛出的异常
在Sa-Token
中,角色和权限可以独立验证
// 获取:当前账号所拥有的角色集合
StpUtil.getRoleList();
// 判断:当前账号是否拥有指定角色, 返回true或false
StpUtil.hasRole("super-admin");
// 校验:当前账号是否含有指定角色标识, 如果验证未通过,则抛出异常: NotRoleException
StpUtil.checkRole("super-admin");
// 校验:当前账号是否含有指定角色标识 [指定多个,必须全部验证通过]
StpUtil.checkRoleAnd("super-admin", "shop-admin");
// 校验:当前账号是否含有指定角色标识 [指定多个,只要其一验证通过即可]
StpUtil.checkRoleOr("super-admin", "shop-admin");
扩展:NotRoleException
对象可通过getLoginType()
方法获取具体是哪个StpLogic
抛出的异常
有同学要问,鉴权失败,抛出异常,然后呢?要把异常显示给用户看吗?当然不可以!
你可以创建一个全局异常拦截器,统一返回给前端的格式,参考:
@RestControllerAdvice
public class GlobalExceptionHandler {
// 全局异常拦截
@ExceptionHandler
public SaResult handlerException(Exception e) {
e.printStackTrace();
return SaResult.error(e.getMessage());
}
}
可参考:码云:GlobalException.java
Sa-Token
允许你根据通配符指定泛权限,例如当一个账号拥有user*
的权限时,user-add
、user-delete
、user-update
都将匹配通过
// 当拥有 user* 权限时
StpUtil.hasPermission("user-add"); // true
StpUtil.hasPermission("user-update"); // true
StpUtil.hasPermission("art-add"); // false
// 当拥有 *-delete 权限时
StpUtil.hasPermission("user-add"); // false
StpUtil.hasPermission("user-delete"); // true
StpUtil.hasPermission("art-delete"); // true
// 当拥有 *.js 权限时
StpUtil.hasPermission("index.js"); // true
StpUtil.hasPermission("index.css"); // false
StpUtil.hasPermission("index.html"); // false
上帝权限:当一个账号拥有
*
权限时,他可以验证通过任何权限码 (角色认证同理)
权限精确到按钮级的意思就是指:权限范围可以控制到页面上的每一个按钮是否显示。
思路:如此精确的范围控制只依赖后端已经难以完成,此时需要前端进行一定的逻辑判断。
如果是前后端一体项目,可以参考:Thymeleaf 标签方言
如果是前后端分离项目,则:
在登录时,把当前账号拥有的所有权限码一次性返回给前端。
前端将权限码集合保存在localStorage或其它全局状态管理对象中。
在需要权限控制的按钮上,使用 js 进行逻辑判断,例如在Vue框架中我们可以使用如是写法:
<button v-if="arr.indexOf('user:delete') > -1">删除按钮button>
其中:arr
是当前用户拥有的权限码数组,user:delete
是显示按钮需要拥有的权限码,删除按钮是用户拥有权限码才可以看到的内容。
注意:以上写法只为提供一个参考示例,不同框架有不同写法,大家可根据项目技术栈灵活封装进行调用。
需要!
前端的鉴权只是一个辅助功能,对于专业人员这些限制都是可以轻松绕过的,为保证服务器安全,无论前端是否进行了权限校验,后端接口都需要对会话请求再次进行权限校验!
上述只提供了登录认证和权限认证的两个功能,Sa-Token
还有如下诸多功能:
登录认证 —— 单端登录、多端登录、同端互斥登录、七天内免登录
权限认证 —— 权限认证、角色认证、会话二级认证
Session
会话 —— 全端共享Session
、单端独享Session
、自定义Session
踢人下线 —— 根据账号id
踢人下线、根据Token
值踢人下线
账号封禁 —— 指定天数封禁、永久封禁、设定解封时间
持久层扩展 —— 可集成Redis
、Memcached
等专业缓存中间件,重启数据不丢失
分布式会话 —— 提供jwt
集成、共享数据中心两种分布式会话方案
微服务网关鉴权 —— 适配Gateway
、ShenYu
、Zuul
等常见网关的路由拦截认证
单点登录
—— 内置三种单点登录模式:无论是否跨域、是否共享Redis,都可以搞定
OAuth2.0
认证 —— 基于RFC-6749
标准编写,OAuth2.0
标准流程的授权认证,支持openid
模式
二级认证 —— 在已登录的基础上再次认证,保证安全性
Basic
认证 —— 一行代码接入Http Basic
认证
独立Redis
—— 将权限缓存与业务缓存分离
临时Token
验证 —— 解决短时间的Token
授权问题
模拟他人账号 —— 实时操作任意用户状态数据
临时身份切换 —— 将会话身份临时切换为其它账号
前后台分离 —— APP
、小程序等不支持Cookie
的终端
同端互斥登录 —— 像QQ
一样手机电脑同时在线,但是两个手机上互斥登录
多账号认证体系 —— 比如一个商城项目的user
表和admin
表分开鉴权
花式token
生成 —— 内置六种Token
风格,还可:自定义Token
生成策略、自定义Token
前缀
注解式鉴权 —— 优雅的将鉴权与业务代码分离
路由拦截式鉴权 —— 根据路由拦截鉴权,可适配restful
模式
自动续签 —— 提供两种Token
过期策略,灵活搭配使用,还可自动续签
会话治理 —— 提供方便灵活的会话查询接口
记住我模式 —— 适配[记住我]模式,重启浏览器免验证
密码加密 —— 提供密码加密模块,可快速MD5
、SHA1
、SHA256
、AES
、RSA
加密
全局侦听器 —— 在用户登陆、注销、被踢下线等关键性操作时进行一些AOP
操作
开箱即用 —— 提供SpringMVC
、WebFlux
等常见web
框架starter
集成包,真正的开箱即用
Maven
依赖
<dependency>
<groupId>cn.dev33groupId>
<artifactId>sa-token-spring-boot-starterartifactId>
<version>1.30.0version>
dependency>
Gradle
依赖implementation 'cn.dev33:sa-token-spring-boot-starter:1.30.0'
jar
包下载点击下载:sa-token-1.6.0.jar
【注意】:当前仅提供v1.6.0
版本jar
包下载,更多版本请前往maven
中央仓库获取,直达链接
Gitee
地址:https://gitee.com/dromara/sa-token
GitHub地址:https://github.com/dromara/sa-token
── sa-token
├── sa-token-core // [核心] Sa-Token 核心模块
├── sa-token-starter // [整合] Sa-Token 与其它框架整合
├── sa-token-servlet // [整合] Sa-Token 整合 Servlet容器实现类包
├── sa-token-spring-boot-starter // [整合] Sa-Token 整合 SpringBoot 快速集成
├── sa-token-reactor-spring-boot-starter // [整合] Sa-Token 整合 Reactor 响应式编程 快速集成
├── sa-token-solon-plugin // [整合] Sa-Token 整合 Solon 快速集成
├── sa-token-jfinal-plugin // [整合] Sa-Token 整合 JFinal 快速集成
├── sa-token-jboot-plugin // [整合] Sa-Token 整合 jboot 快速集成
├── sa-token-plugin // [插件] Sa-Token 插件合集
├── sa-token-dao-redis // [插件] Sa-Token 整合 Redis (使用jdk默认序列化方式)
├── sa-token-dao-redis-jackson // [插件] Sa-Token 整合 Redis (使用jackson序列化方式)
├── sa-token-spring-aop // [插件] Sa-Token 整合 SpringAOP 注解鉴权
├── sa-token-temp-jwt // [插件] Sa-Token 整合 jwt 临时令牌鉴权
├── sa-token-quick-login // [插件] Sa-Token 快速注入登录页插件
├── sa-token-alone-redis // [插件] Sa-Token 独立Redis插件,实现[权限缓存与业务缓存分离]
├── sa-token-sso // [插件] Sa-Token 整合 SSO 单点登录
├── sa-token-oauth2 // [插件] Sa-Token 实现 OAuth2.0 模块
├── sa-token-dialect-thymeleaf // [插件] Sa-Token 标签方言(Thymeleaf版)
├── sa-token-jwt // [插件] Sa-Token 整合 jwt 登录认证
├── sa-token-demo // [示例] Sa-Token 示例合集
├── sa-token-demo-springboot // [示例] Sa-Token 整合 SpringBoot
├── sa-token-demo-springboot-redis // [示例] Sa-Token 整合 SpringBoot
├── sa-token-demo-webflux // [示例] Sa-Token 整合 WebFlux
├── sa-token-demo-jwt // [示例] Sa-Token 集成 jwt
├── sa-token-demo-solon // [示例] Sa-Token 集成 Solon
├── sa-token-demo-quick-login // [示例] Sa-Token 集成 quick-login 模块
├── sa-token-demo-alone-redis // [示例] Sa-Token 集成 alone-redis 模块
├── sa-token-demo-thymeleaf // [示例] Sa-Token 集成 Thymeleaf 标签方言
├── sa-token-demo-jwt // [示例] Sa-Token 集成 jwt 登录认证
├── sa-token-demo-sso-server // [示例] Sa-Token 集成 SSO单点登录-Server认证中心
├── sa-token-demo-sso1-client // [示例] Sa-Token 集成 SSO单点登录-模式一 应用端
├── sa-token-demo-sso2-client // [示例] Sa-Token 集成 SSO单点登录-模式二 应用端
├── sa-token-demo-sso3-client // [示例] Sa-Token 集成 SSO单点登录-模式三 应用端
├── sa-token-demo-sso3-client-nosdk // [示例] Sa-Token 集成 SSO单点登录-模式三 应用端 (不使用sdk,纯手动对接)
├── sa-token-demo-sso-server-h5 // [示例] Sa-Token 集成 SSO单点登录-Server认证中心 (前后端分离)
├── sa-token-demo-sso-client-h5 // [示例] Sa-Token 集成 SSO单点登录-client应用端 (前后端分离)
├── sa-token-demo-oauth2-server // [示例] Sa-Token 集成 OAuth2.0 (服务端)
├── sa-token-demo-oauth2-client // [示例] Sa-Token 集成 OAuth2.0 (客户端)
├── sa-token-demo-websocket // [示例] Sa-Token 集成 Web-Socket 鉴权示例
├── sa-token-demo-websocket-spring // [示例] Sa-Token 集成 Web-Socket(Spring封装版) 鉴权示例
├── sa-token-test // [测试] Sa-Token 单元测试合集
├── sa-token-core-test // [测试] Sa-Token Core核心包单元测试
├── sa-token-springboot-test // [测试] Sa-Token SpringBoot 整合测试
├── sa-token-springboot-integrate-test // [测试] Sa-Token SpringBoot 整合客户端测试
├── sa-token-jwt-test // [测试] Sa-Token jwt 整合测试
├── sa-token-doc // [文档] Sa-Token 开发文档
├──pom.xml // [依赖] 顶级pom文件
下载代码(学习测试用master
分支)。
从根目录导入项目。
选择相应的示例添加为Maven
项目,打开XxxApplication.java
运行。
在IDE
中新建一个SpringBoot
项目,例如:sa-token-demo-springboot
(不会的同学请自行百度或者参考:SpringBoot-Pure)
在pom.xml
中添加依赖:
<dependency>
<groupId>cn.dev33groupId>
<artifactId>sa-token-spring-boot-starterartifactId>
<version>1.30.0version>
dependency>
你可以零配置启动项目 ,但同时你也可以在 application.yml 中增加如下配置,定制性使用框架:
server:
# 端口
port: 8081
# Sa-Token配置
sa-token:
# token 名称 (同时也是cookie名称)
token-name: satoken
# token 有效期,单位s 默认30天, -1代表永不过期
timeout: 2592000
# token 临时有效期 (指定时间内无操作就视为token过期) 单位: 秒
activity-timeout: -1
# 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录)
is-concurrent: true
# 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)
is-share: false
# token风格
token-style: uuid
# 是否输出操作日志
is-log: false
如果你习惯于application.properties
类型配置文件,那也很好办:
百度: springboot properties与yml 配置文件的区别
在项目中新建包com.pj
,在此包内新建主类 SaTokenDemoApplication.java
,复制以下代码:
@SpringBootApplication
public class SaTokenDemoApplication {
public static void main(String[] args) throws JsonProcessingException {
SpringApplication.run(SaTokenDemoApplication.class, args);
System.out.println("启动成功:Sa-Token配置如下:" + SaManager.getConfig());
}
}
Controller
@RestController
@RequestMapping("/user/")
public class UserController {
// 测试登录,浏览器访问: http://localhost:8081/user/doLogin?username=zhang&password=123456
@RequestMapping("doLogin")
public String doLogin(String username, String password) {
// 此处仅作模拟示例,真实项目需要从数据库中查询数据进行比对
if("zhang".equals(username) && "123456".equals(password)) {
StpUtil.login(10001);
return "登录成功";
}
return "登录失败";
}
// 查询登录状态,浏览器访问: http://localhost:8081/user/isLogin
@RequestMapping("isLogin")
public String isLogin() {
return "当前会话是否登录:" + StpUtil.isLogin();
}
}
启动代码,从浏览器依次访问上述测试接口:
Reactor
是一种非阻塞的响应式模型,以WebFlux
为例来展示Sa-Token
与
Reactor
响应式模型框架相整合的示例, 你可以用同样方式去对接其它 Reactor
模型框架(Netty
、ShenYu
、SpringCloud Gateway
等)
整合示例在官方仓库的/sa-token-demo/sa-token-demo-webflux
文件夹下,如遇到难点可结合源码进行测试学习
WebFlux
用于微服务网关架构中,如果您的应用基于单体架构且非Reactor
模型
在IDE
中新建一个SpringBoot
项目,例如:sa-token-demo-webflux
在pom.xml
中添加依赖:
<!-- Sa-Token 权限认证(Reactor响应式集成), 在线文档:http://sa-token.dev33.cn/ -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-reactor-spring-boot-starter</artifactId>
<version>1.30.0</version>
</dependency>
在项目中新建包com.pj
,在此包内新建主类 SaTokenDemoApplication.java
,输入以下代码:
@SpringBootApplication
public class SaTokenDemoApplication {
public static void main(String[] args) throws JsonProcessingException {
SpringApplication.run(SaTokenDemoApplication.class, args);
System.out.println("启动成功:Sa-Token配置如下:" + SaManager.getConfig());
}
}
新建SaTokenConfigure.java
,注册Sa-Token
的全局过滤器
/**
* [Sa-Token 权限认证] 全局配置类
*/
@Configuration
public class SaTokenConfigure {
/**
* 注册 [Sa-Token全局过滤器]
*/
@Bean
public SaReactorFilter getSaReactorFilter() {
return new SaReactorFilter()
// 指定 [拦截路由]
.addInclude("/**")
// 指定 [放行路由]
.addExclude("/favicon.ico")
// 指定[认证函数]: 每次请求执行
.setAuth(obj -> {
System.out.println("---------- sa全局认证");
// SaRouter.match("/test/test", () -> StpUtil.checkLogin());
})
// 指定[异常处理函数]:每次[认证函数]发生异常时执行此函数
.setError(e -> {
System.out.println("---------- sa全局异常 ");
return SaResult.error(e.getMessage());
})
;
}
}
你只需要按照此格式复制代码即可。
Controller
@RestController
@RequestMapping("/user/")
public class UserController {
// 测试登录,浏览器访问: http://localhost:8081/user/doLogin?username=zhang&password=123456
@RequestMapping("doLogin")
public String doLogin(String username, String password) {
// 此处仅作模拟示例,真实项目需要从数据库中查询数据进行比对
if("zhang".equals(username) && "123456".equals(password)) {
StpUtil.login(10001);
return "登录成功";
}
return "登录失败";
}
// 查询登录状态,浏览器访问: http://localhost:8081/user/isLogin
@RequestMapping("isLogin")
public String isLogin() {
return "当前会话是否登录:" + StpUtil.isLogin();
}
}
启动代码,从浏览器依次访问上述测试接口:
Sa-Token
框架是一个轻量级的登录、鉴权框架,有利于我们开发。
. Sa-Token
框架的官方文档:https://sa-token.dev33.cn/doc/index.html