sa-token/sa-token-doc/use/login-auth.md

181 lines
6.5 KiB
Markdown
Raw Normal View History

2021-04-30 23:48:12 +08:00
# 登录认证
2022-10-14 01:33:14 +08:00
2020-02-06 00:52:49 +08:00
---
2023-06-21 23:10:29 +08:00
### 1、设计思路
2020-02-06 00:52:49 +08:00
对于一些登录之后才能访问的接口(例如:查询我的账号资料),我们通常的做法是增加一层接口校验:
- 如果校验通过,则:正常返回数据。
- 如果校验未通过,则:抛出异常,告知其需要先进行登录。
那么,判断会话是否登录的依据是什么?我们先来简单分析一下登录访问流程:
1. 用户提交 `name` + `password` 参数,调用登录接口。
2. 登录成功,返回这个用户的 Token 会话凭证。
3. 用户后续的每次请求,都携带上这个 Token。
4. 服务器根据 Token 判断此会话是否登录成功。
2022-10-14 01:33:14 +08:00
所谓登录认证,指的就是服务器校验账号密码,为用户颁发 Token 会话凭证的过程,这个 Token 也是我们后续判断会话是否登录的关键所在。
2020-02-06 00:52:49 +08:00
2022-05-09 17:35:29 +08:00
<button class="show-img" img-src="https://oss.dev33.cn/sa-token/doc/g/g3--login-auth.gif">加载动态演示图</button>
2023-06-21 23:10:29 +08:00
### 2、登录与注销
根据以上思路,我们需要一个会话登录的函数:
2020-02-06 00:52:49 +08:00
2021-01-31 23:28:42 +08:00
``` java
// 会话登录参数填写要登录的账号id建议的数据类型long | int | String 不可以传入复杂类型User、Admin 等等
2021-06-16 20:24:23 +08:00
StpUtil.login(Object id);
```
只此一句代码便可以使会话登录成功实际上Sa-Token 在背后做了大量的工作,包括但不限于:
2023-06-21 23:10:29 +08:00
1. 检查此账号是否之前已有登录;
2. 为账号生成 `Token` 凭证与 `Session` 会话;
3. 记录 Token 活跃时间;
4. 通知全局侦听器xx 账号登录成功;
5.`Token` 注入到请求上下文;
6. 等等其它工作……
2023-06-21 23:10:29 +08:00
你暂时不需要完整了解整个登录过程,你只需要记住关键一点:`Sa-Token 为这个账号创建了一个Token凭证且通过 Cookie 上下文返回给了前端`。
所以一般情况下,我们的登录接口代码,会大致类似如下:
``` java
// 会话登录接口
@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("登录失败");
}
```
2023-06-21 23:10:29 +08:00
如果你对以上代码阅读没有压力,你可能会注意到略显奇怪的一点:此处仅仅做了会话登录,但并没有主动向前端返回 token 信息。
是因为不需要吗?严格来讲是需要的,只不过 `StpUtil.login(id)` 方法利用了 Cookie 自动注入的特性,省略了你手写返回 token 的代码。
如果你对 Cookie 功能还不太了解,也不用担心,我们会在之后的 [ 前后端分离 ] 章节中详细的阐述 Cookie 功能,现在你只需要了解最基本的两点:
2020-02-06 00:52:49 +08:00
2023-06-21 23:10:29 +08:00
- Cookie 可以从后端控制往浏览器中写入 token 值。
- Cookie 会在前端每次发起请求时自动提交 token 值。
因此,在 Cookie 功能的加持下,我们可以仅靠 `StpUtil.login(id)` 一句代码就完成登录认证。
除了登录方法,我们还需要:
``` java
2021-01-31 23:28:42 +08:00
// 当前会话注销登录
StpUtil.logout();
2020-02-06 00:52:49 +08:00
2021-01-31 23:28:42 +08:00
// 获取当前会话是否已经登录返回true=已登录false=未登录
StpUtil.isLogin();
2020-05-02 15:19:55 +08:00
2021-01-31 23:28:42 +08:00
// 检验当前会话是否已经登录, 如果未登录,则抛出异常:`NotLoginException`
StpUtil.checkLogin();
2021-01-31 23:28:42 +08:00
```
2020-02-06 00:52:49 +08:00
异常 `NotLoginException` 代表当前会话暂未登录,可能的原因有很多:
2023-06-21 23:10:29 +08:00
前端没有提交 token、前端提交的 token 是无效的、前端提交的 token 已经过期 …… 等等,可参照此篇:[未登录场景值](/fun/not-login-scene),了解如何获取未登录的场景值。
2021-01-31 23:28:42 +08:00
2023-06-21 23:10:29 +08:00
### 3、会话查询
2021-01-31 23:28:42 +08:00
``` java
2021-07-21 14:39:50 +08:00
// 获取当前会话账号id, 如果未登录,则抛出异常:`NotLoginException`
2021-01-31 23:28:42 +08:00
StpUtil.getLoginId();
// 类似查询API还有
2021-07-21 14:39:50 +08:00
StpUtil.getLoginIdAsString(); // 获取当前会话账号id, 并转化为`String`类型
StpUtil.getLoginIdAsInt(); // 获取当前会话账号id, 并转化为`int`类型
StpUtil.getLoginIdAsLong(); // 获取当前会话账号id, 并转化为`long`类型
2021-01-31 23:28:42 +08:00
// ---------- 指定未登录情形下返回的默认值 ----------
2023-06-21 23:10:29 +08:00
// 获取当前会话账号id, 如果未登录,则返回 null
2021-01-31 23:28:42 +08:00
StpUtil.getLoginIdDefaultNull();
2021-07-21 14:39:50 +08:00
// 获取当前会话账号id, 如果未登录,则返回默认值 `defaultValue`可以为任意类型)
2021-01-31 23:28:42 +08:00
StpUtil.getLoginId(T defaultValue);
```
2023-06-21 23:10:29 +08:00
### 4、token 查询
2021-01-31 23:28:42 +08:00
``` java
2023-06-21 23:10:29 +08:00
// 获取当前会话的 token 值
StpUtil.getTokenValue();
2021-01-31 23:28:42 +08:00
2023-06-21 23:10:29 +08:00
// 获取当前`StpLogic`的 token 名称
2021-01-31 23:28:42 +08:00
StpUtil.getTokenName();
2023-06-21 23:10:29 +08:00
// 获取指定 token 对应的账号id如果未登录则返回 null
StpUtil.getLoginIdByToken(String tokenValue);
// 获取当前会话剩余有效期单位s返回-1代表永久有效
StpUtil.getTokenTimeout();
2021-01-31 23:28:42 +08:00
2023-06-21 23:10:29 +08:00
// 获取当前会话的 token 信息参数
2021-01-31 23:28:42 +08:00
StpUtil.getTokenInfo();
```
有关`TokenInfo`参数详解,请参考:[TokenInfo参数详解](/fun/token-info)
2021-09-14 22:18:42 +08:00
2023-06-21 23:10:29 +08:00
### 5、来个小测试加深一下理解
新建 `LoginController`,复制或手动敲出以下代码
2021-09-14 22:18:42 +08:00
``` java
/**
* 登录测试
*/
@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());
}
2021-10-21 02:43:27 +08:00
// 查询 Token 信息 ---- http://localhost:8081/acc/tokenInfo
@RequestMapping("tokenInfo")
public SaResult tokenInfo() {
return SaResult.data(StpUtil.getTokenInfo());
}
2021-09-14 22:18:42 +08:00
// 测试注销 ---- http://localhost:8081/acc/logout
@RequestMapping("logout")
public SaResult logout() {
StpUtil.logout();
return SaResult.ok();
}
}
```
2020-02-06 00:52:49 +08:00
2022-10-11 18:00:47 +08:00
---
2022-10-17 00:25:28 +08:00
<a class="case-btn" href="https://gitee.com/dromara/sa-token/blob/master/sa-token-demo/sa-token-demo-case/src/main/java/com/pj/cases/use/LoginAuthController.java"
target="_blank">
2024-05-06 12:01:07 +08:00
本章代码示例Sa-Token 登录认证 —— [ LoginAuthController.java ]
2022-10-17 00:25:28 +08:00
</a>
2022-10-11 18:00:47 +08:00
<a class="dt-btn" href="https://www.wenjuan.ltd/s/UZBZJvb2ej/" target="_blank">本章小练习Sa-Token 基础 - 登录认证,章节测试</a>
2020-02-06 00:52:49 +08:00