docs: 文档优化 [登录认证] 篇

This commit is contained in:
click33
2025-12-27 16:47:49 +08:00
parent 4b7e6d651f
commit a6a1b9b865
2 changed files with 102 additions and 35 deletions

View File

@@ -8,6 +8,12 @@ body{font-family: -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu
.main-box .markdown-section{ /* padding: 38px 20px; */ max-width: 100%; /* margin-left: 12%; */}
.main-box .markdown-section h4{font-size: 1rem;}
.main-box red, .main-box red *{ color: red !important; }
.main-box green, .main-box green *{ color: green !important; }
.main-box blue, .main-box blue *{ color: blue;!important; }
.main-box purple, .main-box purple *{ color: purple;!important; }
.main-box question, .main-box question *{ color: purple;!important; }
/* ------- 多设备适配 start ------- */

View File

@@ -3,44 +3,38 @@
---
### 1、设计思路
### 1、开始登录
对于一些登录之后才能访问的接口(例如:查询我的账号资料),我们通常的做法是增加一层接口校验
一个完整的登录认证包含哪些步骤?让我们代入用户视角:在打开 网站/APP 后,用户的操作流程大致可以概括为
1. 打开 网站/APP进入登录页。
2. 输入 账号+密码 进行登录。
3. 进入首页,进行业务相关操作。
4. 注销登录,关闭 网站/APP。
- 如果校验通过,则:正常返回数据。
- 如果校验未通过,则:抛出异常,告知其需要先进行登录。
在整个流程中Sa-Token 负责哪些部分呢? 下图可以帮助你理解:
那么,判断会话是否登录的依据是什么?我们先来简单分析一下登录访问流程:
![基础-登录认证流程图.svg](../big-file/use/基础-登录认证流程图.svg 'w-100')
1. 用户提交 `name` + `password` 参数,调用登录接口
2. 登录成功,返回这个用户的 Token 会话凭证。
3. 用户后续的每次请求,都携带上这个 Token。
4. 服务器根据 Token 判断此会话是否登录成功。
如上图所示:<green>**无论用户采用何种登录方式,本质上都是通过提交一定的认证信息,使系统可以定位到 Ta 的唯一标识 —— userId**</green>
所谓登录认证,指的就是服务器校验账号密码,为用户颁发 Token 会话凭证的过程,这个 Token 也是我们后续判断会话是否登录的关键所在。
<button class="show-img" img-src="https://oss.dev33.cn/sa-token/doc/g/g3--login-auth.gif">加载动态演示图</button>
### 2、登录与注销
根据以上思路,我们需要一个会话登录的函数:
当我们拿到 userId 后,便可以调用框架提供的 API 进行登录:
``` java
// 会话登录参数填写要登录的账号id建议的数据类型long | int | String 不可以传入复杂类型User、Admin 等等
StpUtil.login(Object id);
StpUtil.login(Object userId);
```
只此一句代码,便可以使会话登录成功实际上Sa-Token 在背后做了大量的工作,包括但不限于:
只此一句代码,便可以使会话登录成功实际上Sa-Token 在背后做了大量的工作,包括但不限于:
1. 检查此账号是否之前已有登录;
2. 为账号生成 `Token` 凭证与 `Session` 会话;
2. 为账号生成 Token 凭证与 Session 会话;
3. 记录 Token 活跃时间;
4. 通知全局侦听器xx 账号登录成功;
5. 将 `Token` 注入到请求上下文
6. 等等其它工作……
5. 检查此账号登录数量是否已达上限
6. 将 Token 注入到请求上下文;
7. 等等其它工作……
你暂时不需要完整了解整个登录过程,你只需要记住关键一点:`Sa-Token 为这个账号创建了一个Token凭证且通过 Cookie 上下文返回给了前端`
你暂时不需要完整了解整过程,你只需要记住关键一点:<green>**Sa-Token 为这个账号创建了一个 token 凭证,且通过 Cookie 上下文返回给了前端**</green>
所以一般情况下,我们的登录接口代码,会大致类似如下:
@@ -58,9 +52,9 @@ public SaResult doLogin(String name, String pwd) {
}
```
如果你对以上代码阅读没有压力,你可能会注意到略显奇怪的一点:此处仅仅做了会话登录,但并没有主动向前端返回 token 信息。
是因为不需要吗?严格来讲是需要的,只不过 `StpUtil.login(id)` 方法利用了 Cookie 自动注入的特性,省略了你手写返回 token 的代码。
如果你对以上代码阅读没有压力,你可能会注意到略显奇怪的一点:<green>**此处仅仅做了会话登录,但并没有主动向前端返回 token 信息。**</green>
是因为不需要吗?严格来讲是需要的,只不过 `StpUtil.login(id)` 方法利用了 Cookie 自动注入的特性,省略了你手写返回 token 的代码。
> [!TIP| label:Cookie 是什么?]
> 如果你对 Cookie 功能还不太了解,也不用担心,我们会在之后的 [ 前后端分离 ] 章节中详细的阐述 Cookie 功能,现在你只需要了解最基本的两点:
@@ -75,25 +69,77 @@ public SaResult doLogin(String name, String pwd) {
> <button class="show-img" img-src="https://oss.dev33.cn/sa-token/doc/use/sa-login-cookie-pre.png">加载演示图</button>
### 2、校验是否登录
除了登录方法,我们还需要
对于一些登录之后才能访问的接口(例如:查询我的账号资料),我们通常的做法是增加一层接口校验
- 如果校验通过,则:<green>正常返回数据。</green>
- 如果校验未通过,则:<red>抛出异常,告知其需要先进行登录。</red>
![基础-登录校验流程图.svg](../big-file/use/基础-登录校验流程图.svg 'w-100')
<!-- <button class="show-img" img-src="https://oss.dev33.cn/sa-token/doc/g/g3--login-auth.gif">加载动态演示图</button> -->
使用以下方法判断当前会话是否已登录:
``` java
// 当前会话注销登录
StpUtil.logout();
// 获取当前会话是否已经登录返回true=已登录false=未登录
// 判断当前会话是否已经登录,返回 true=已登录false=未登录
StpUtil.isLogin();
// 检验当前会话是否已经登录, 如果登录则抛出异常:`NotLoginException`
// 检验当前会话是否已经登录, 如果登录代码会安全通过,未登录则抛出异常:`NotLoginException`
StpUtil.checkLogin();
```
异常 `NotLoginException` 代表当前会话暂未登录,可能的原因有很多
前端没有提交 token、前端提交的 token 是无效的、前端提交的 token 已经过期 …… 等等,可参照此篇:[未登录场景值](/fun/not-login-scene),了解如何获取未登录的场景值。
例如我们可以在接口内,根据是否登录返回不同的信息
``` java
// 获取我的资料信息
@RequestMapping("myInfo")
public String myInfo() {
if( StpUtil.isLogin() ) {
// ...
return "我的资料信息...";
} else {
return "未登录,请先登录";
}
}
```
或者在未登录时直接抛出全局异常:
``` java
// 获取我的资料信息
@RequestMapping("myInfo")
public String myInfo() {
StpUtil.checkLogin(); // 如果当前未登录,这句代码会直接抛出异常 `NotLoginException`
return "我的资料信息";
}
```
配合全局异常处理器,统一返回固定格式数据到前端:
``` java
@RestControllerAdvice
public class GlobalException {
@ExceptionHandler(NotLoginException.class)
public SaResult handlerException(NotLoginException e) {
return SaResult.error(e.getMessage());
}
}
```
异常 <red>`NotLoginException`</red> 代表当前会话暂未登录,可能的原因有很多:
- 前端没有提交 token。
- 前端提交的 token 是无效的。
- 前端提交的 token 已经过期。
- ……
可参照此篇:[未登录场景值](/fun/not-login-scene),了解如何获取未登录的场景值。
### 3、会话查询
如果你想要获取当前登录的是谁:
``` java
// 获取当前会话账号id, 如果未登录,则抛出异常:`NotLoginException`
StpUtil.getLoginId();
@@ -103,7 +149,7 @@ StpUtil.getLoginIdAsString(); // 获取当前会话账号id, 并转化为`Str
StpUtil.getLoginIdAsInt(); // 获取当前会话账号id, 并转化为`int`类型
StpUtil.getLoginIdAsLong(); // 获取当前会话账号id, 并转化为`long`类型
// ---------- 指定未登录情形下返回的默认值 ----------
// ---------- 以下方法可以指定未登录情形下返回的默认值 ----------
// 获取当前会话账号id, 如果未登录,则返回 null
StpUtil.getLoginIdDefaultNull();
@@ -134,7 +180,14 @@ StpUtil.getTokenInfo();
有关`TokenInfo`参数详解,请参考:[TokenInfo参数详解](/fun/token-info)
### 5、来个小测试,加深一下理解
### 5、会话注销
``` java
// 当前会话注销登录
StpUtil.logout();
```
### 6、来个小测试加深一下理解
新建 `LoginController`,复制或手动敲出以下代码
``` java
/**
@@ -186,3 +239,11 @@ public class LoginController {
</a>
<a class="dt-btn" href="https://www.wenjuan.ltd/s/UZBZJvb2ej/" target="_blank">本章小练习Sa-Token 基础 - 登录认证,章节测试</a>