Files
PoJie/ruoyi-server/docs/LOGIN_COMPREHENSIVE_GUIDE.md
T
2026-02-22 12:12:02 +08:00

719 lines
33 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 登录模块综合开发指南(LOGIN_COMPREHENSIVE_GUIDE
版本:v1.1.02025-12-27
适用范围:Sys(后台管理端)、App(移动端)两套登录体系及微信公众号整合
最后更新:2025-12-27
---
## 目录
1. 登录模块概述
2. 详细开发指南
3. 登录流程示意图
4. 实现方案
5. 模块规范
6. App 会话管理 API
7. Sys 在线用户管理 API
8. Sys 登录日志管理 API
9. 相关代码路径参考
---
## 1. 登录模块概述
- 背景与目的
- 系统同时支持 Sys 与 App 两套登录体系,分别面向管理员与 C 端用户,要求登录态、权限与数据完全隔离,同时提供统一的扩展与维护指引。
- 采用策略模式(Strategy Pattern)实现登录方式的可插拔扩展,基于 Sa-Token 管理会话与权限,支持验证码、限流、并发与设备维度会话。
- 集成微信公众号能力:App 用于授权登录与业务交互;Sys 用于管理员绑定与模板消息推送。
- 目标
- 统一规范开发流程与接口定义,保障多端、多方式登录的稳定性与可扩展性。
- 为新增登录方式与微信能力提供清晰的落地步骤与测试方案。
---
## 2. 详细开发指南
### 2.1 多用户体系与会话隔离
- 物理隔离 + 逻辑统一:`sys_user``app_user` 两套用户体系;统一使用 Sa-Token 管理会话。
- LoginId 前缀隔离:
- Sys`sys_user:{id}`
- App`app:{id}`
- 会话校验(Sys 全局拦截):参考 SecurityConfig 的 `StpUtil.checkLogin()` 与路由校验,确保 Token 与 clientid 一致。
### 2.2 App 开发要点
- 策略模式登录:`IAppAuthStrategy``grantType` 路由到具体策略(密码、短信、社交、微信等)。
- 验证码与密码重试:`captcha.enable=true` 可开关;错误次数与锁定时间通过配置项控制。
- 信息补全向导(过滤器):登录后若用户资料未完善,仅放行“查询个人信息/绑定手机号”接口,其余拦截返回 403。
### 2.3 Sys 开发要点
- 安全加固:
- 异地登录检测:比对最近一次登录 IP 归属地变化并告警(日志/邮件)。
- 强制改密策略:登录后检查密码更新时间是否超期,超期在 Session 写入标记,拦截除改密外所有接口。
- 管理员微信绑定与消息推送:后台生成带参二维码,管理员扫码绑定 `openId/unionId`,用于模板消息推送。
(最小改动策略)
- 保留现有 Sys 登录与权限实现,不做核心代码改造。
- 新增或接入的仅为“管理员微信绑定二维码生成”“SCAN/SUBSCRIBE 回调绑定”“模板消息推送”三个能力点;其余增强(如异地登录与强制改密)可按需增量加入,不影响主流程。
### 2.4 微信公众号整合(双端)
- AppOAuth2 获取 `openId/unionId`,优先 `unionId` 进行跨应用账号识别;若未绑定则返回 401 并引导绑定手机号。
- Sys:生成 `scene_str=sys_user:{userId}` 的二维码,接收 `SCAN/SUBSCRIBE` 事件解析并绑定,后续通过模板消息进行系统通知与订单推送。
---
## 3. 登录流程示意图
### 3.1 App 登录总体流程
```mermaid
sequenceDiagram
participant Client as 客户端
participant Controller as AppAuthController
participant Strategy as IAppAuthStrategy
participant Service as AppLoginService
participant Redis as Redis
Client->>Controller: POST /app/auth/login
Controller->>Strategy: authenticate(body, client, grantType)
Strategy->>Service: checkLogin(...)
Service->>Redis: PWD_ERR_CNT_KEY
Strategy->>Controller: LoginVo(token, expire)
Controller-->>Client: 返回结果
```
### 3.2 App 微信公众号授权登录
```mermaid
sequenceDiagram
participant H5 as 前端网页
participant Wx as 微信OAuth2
participant AppAPI as AppAuthController
participant MP as WxMpService
H5->>Wx: 跳转授权,获取code
H5->>AppAPI: grantType=wechat_mp, code
AppAPI->>MP: getAccessToken(code)
MP-->>AppAPI: openId, accessToken
AppAPI->>MP: userInfo(openId)
MP-->>AppAPI: unionId
AppAPI->>DB: 查询app_social_auth by unionId
alt 已绑定
AppAPI-->>H5: 登录成功
else 未绑定
AppAPI-->>H5: 401_BIND_REQUIRED + tempKey
end
```
### 3.3 Sys 管理员绑定与模板消息推送
```mermaid
flowchart LR
A[管理员点击绑定] --> B[生成带参二维码 scene_str=sys_user:{userId}]
B --> C[管理员扫码]
C --> D[WxMpPortal接收SCAN/SUBSCRIBE]
D --> E[解析EventKey与OpenId]
E --> F[查询UnionId]
F --> G[更新管理员绑定信息]
G --> H[SysMessageService发送模板消息]
```
---
## 4. 实现方案
### 4.1 架构与技术选型
- Sa-Token:统一的会话与权限管理(Token 名称、并发、多设备)。
- 策略模式:按 `grantType` 定位不同登录策略,低耦合、易扩展。
- WxJava`ruoyi-mp` 模块提供的公众号 OAuth2 与模板消息能力。
- 线程池与并发:按需启用全局线程池或在 JDK21 使用虚拟线程。
### 4.2 关键实现细节
- LoginId 前缀实现:`LoginUser.getLoginId()` 返回 `userType + ":" + userId`
- App 密码策略:开启验证码校验时执行 `validateCaptcha()`;错误次数与锁定时间通过配置项 `user.password.maxRetryCount``user.password.lockTime` 控制。
- App 信息补全:过滤器中检查 `infoComplete`,仅放行指定白名单接口(配置项 `user.auth.whitelist`),其余拦截返回 403。
- App 微信授权:`getAccessToken(code) → userInfo(openId)`,优先使用 `unionId` 识别;未绑定返回 401 与临时 Key,引导绑定手机号。
- Sys 管理员绑定:二维码 `scene_str=sys_user:{userId}`;接收事件后解析 `EventKey``OpenId`,查询 `unionId` 并写入绑定信息;后续根据 `openId` 推送模板消息。
- 异地登录检测:在记录登录信息时调用 `LoginRiskService.checkRisk(userId, ip)`,比较归属地变化并告警。
- 强制改密:登录后检查密码更新时间是否超期,标记 Session 并在拦截器中只放行改密接口。
### 4.4 配置项说明
- **验证码配置**`application.yml`):
```yaml
captcha:
enable: true # 是否启用验证码校验
type: MATH # 验证码类型(MATH数学计算 / CHAR字符验证)
category: CIRCLE # 干扰类型(LINE线段 / CIRCLE圆圈 / SHEAR扭曲)
numberLength: 1 # 数字验证码位数
charLength: 4 # 字符验证码长度
```
- **用户密码策略配置**`application.yml`):
```yaml
user:
password:
maxRetryCount: 5 # 密码最大错误次数
lockTime: 10 # 密码锁定时间(分钟)
```
- **App端验证码与白名单配置**(`application.yml`):
```yaml
user:
auth:
captcha:
enabled: false # App端验证码开关
type: math # 验证码类型
whitelist: /app/user/profile,/app/user/bind,/app/auth/logout # 信息补全白名单
```
- **客户端配置**:在 `sys_client` 表中配置客户端信息,包括 `client_id`、`grant_type`(支持多个,逗号分隔)、`status`、`timeout`、`active_timeout` 等。
### 4.3 OAuth 与 MP 职责划分
- 第三方登录(OAuth):使用 justauth
- 属性来源:`application*.yml` 中的 `justauth.type.*`
- 代码路径:属性绑定 [SocialProperties](file:///Users/lihaha/Documents/Projecte/PoJie/PoJie/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/config/properties/SocialProperties.java),工厂方法 [SocialUtils.getAuthRequest](file:///Users/lihaha/Documents/Projecte/PoJie/PoJie/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/utils/SocialUtils.java#L35-L74)
- 使用位置:App 端策略 [AppWechatMpAuthStrategy](file:///Users/lihaha/Documents/Projecte/PoJie/PoJie/ruoyi-server/src/main/java/org/dromara/app/service/impl/AppWechatMpAuthStrategy.java)、[AppWechatOpenAuthStrategy](file:///Users/lihaha/Documents/Projecte/PoJie/PoJie/ruoyi-server/src/main/java/org/dromara/app/service/impl/AppWechatOpenAuthStrategy.java)、[AppWechatMiniprogramAuthStrategy](file:///Users/lihaha/Documents/Projecte/PoJie/PoJie/ruoyi-server/src/main/java/org/dromara/app/service/impl/AppWechatMiniprogramAuthStrategy.java)
- 说明:source 包含 `wechat_mp`、`wechat_open`、`wechat_miniprogram`、`github`、`gitee` 等,统一由 justauth 提供 OAuth 能力
- 公众号服务端能力(MP):使用 `wx.*`
- 属性来源:`application*.yml` 中的 `wx.mp.*`、`wx.miniapp.*`、`wx.pay.*`
- 代码路径:属性绑定 [WxMpProperties](file:///Users/lihaha/Documents/Projecte/PoJie/PoJie/ruoyi-modules/ruoyi-mp/src/main/java/org/dromara/mp/config/WxMpProperties.java),装配 [WxMpConfiguration](file:///Users/lihaha/Documents/Projecte/PoJie/PoJie/ruoyi-modules/ruoyi-mp/src/main/java/org/dromara/mp/config/WxMpConfiguration.java)
- 使用位置:消息入口 [WxMpPortalController](file:///Users/lihaha/Documents/Projecte/PoJie/PoJie/ruoyi-modules/ruoyi-mp/src/main/java/org/dromara/mp/controller/WxMpPortalController.java)、二维码接口 [WxMpQrCodeController](file:///Users/lihaha/Documents/Projecte/PoJie/PoJie/ruoyi-modules/ruoyi-mp/src/main/java/org/dromara/mp/controller/WxMpQrCodeController.java)
- 说明:MP 提供消息接收、二维码、模板消息推送等服务端功能,不用于 OAuth 登录
---
## 5. 模块规范
### 5.1 接口定义与参数
#### Sys 登录接口
- **路径**`/auth/login`
- **方法**`POST`
- **支持的grantType**
- `password` - 密码登录(参数:`username`, `password`, 可选 `code/uuid`验证码)
- `sms` - 短信登录(参数:`phonenumber`, `smsCode`
- `email` - 邮箱登录(参数:`email`, `emailCode`
- `social` - 第三方登录(参数:`source`, `socialCode`, `socialState`
- **通用参数**`clientId`(必填)
- **返回**`LoginVo`(包含 `accessToken`, `expireIn`, `clientId`
- **代码路径**[AuthController.login](file:///Users/lihaha/Documents/Projecte/PoJie/PoJie/ruoyi-server/src/main/java/org/dromara/web/controller/AuthController.java#L75-L101)
#### Sys 退出登录接口
- **路径**`/auth/logout`
- **方法**`POST`
- **权限**:需要登录态
- **说明**:退出当前登录会话,清除Token
- **代码路径**[AuthController.logout](file:///Users/lihaha/Documents/Projecte/PoJie/PoJie/ruoyi-server/src/main/java/org/dromara/web/controller/AuthController.java#L164-L168)
#### Sys 用户注册接口
- **路径**`/auth/register`
- **方法**`POST`
- **参数**`username`, `password`, `userType`, 可选 `code/uuid`(验证码)
- **说明**:系统用户注册,需系统开启注册功能
- **代码路径**[AuthController.register](file:///Users/lihaha/Documents/Projecte/PoJie/PoJie/ruoyi-server/src/main/java/org/dromara/web/controller/AuthController.java#L174-L181)
#### Sys 第三方绑定接口
- **获取绑定URL**`GET /auth/binding/{source}?domain={domain}`
- 生成第三方授权跳转URL,用于绑定第三方账号
- **回调绑定**`POST /auth/social/callback`
- 前端回调后绑定第三方账号(需token)
- **取消绑定**`DELETE /auth/unlock/{socialId}`
- 取消已绑定的第三方账号(需token)
- **代码路径**[AuthController](file:///Users/lihaha/Documents/Projecte/PoJie/PoJie/ruoyi-server/src/main/java/org/dromara/web/controller/AuthController.java#L109-L158)
#### App 登录接口
- **路径**`/app/auth/login`
- **方法**`POST`
- **支持的grantType**
- `app_password` - 密码登录(参数:`username`, `password`
- `sms` - 短信登录(参数:`phonenumber`, `smsCode`
- `email` - 邮箱登录(参数:`email`, `emailCode`
- `social` - 第三方登录(参数:`source`, `socialCode`, `socialState`
- `wechat_mp` - 微信公众号登录(参数:`socialCode`, `socialState`
- `wechat_open` - 微信开放平台登录(参数:`socialCode`, `socialState`
- `wechat_miniprogram` - 微信小程序登录(参数:`socialCode`, `socialState`
- **通用参数**`clientId`(必填)
- **返回**`LoginVo`(包含 `accessToken`, `expireIn`, `clientId`
- **代码路径**[AppAuthController.login](file:///Users/lihaha/Documents/Projecte/PoJie/PoJie/ruoyi-server/src/main/java/org/dromara/app/controller/AppAuthController.java#L69-L93)
#### App 退出登录接口
- **路径**`/app/auth/logout`
- **方法**`POST`
- **权限**:需要登录态
- **说明**:退出当前登录会话,清除Token
- **代码路径**[AppAuthController.logout](file:///Users/lihaha/Documents/Projecte/PoJie/PoJie/ruoyi-server/src/main/java/org/dromara/app/controller/AppAuthController.java#L100-L104)
#### App 用户注册接口
- **路径**`/app/auth/register`
- **方法**`POST`
- **参数**`username`, `password`
- **限流**:60秒内最多1次(按IP)
- **说明**:App用户注册,需系统开启注册功能
- **代码路径**[AppAuthController.register](file:///Users/lihaha/Documents/Projecte/PoJie/PoJie/ruoyi-server/src/main/java/org/dromara/app/controller/AppAuthController.java#L115-L132)
#### App 配置接口
- **路径**`/app/auth/config`
- **方法**`GET`
- **说明**:获取App端配置信息(如注册开关等)
- **代码路径**[AppAuthController.getConfig](file:///Users/lihaha/Documents/Projecte/PoJie/PoJie/ruoyi-server/src/main/java/org/dromara/app/controller/AppAuthController.java#L139-L145)
#### 验证码接口
- **图形验证码**`GET /auth/code`
- 返回:`CaptchaVo`(包含 `uuid`, `img`Base64图片), `captchaEnabled`
- 限流:60秒内最多10次(按IP)
- **代码路径**[CaptchaController.getCode](file:///Users/lihaha/Documents/Projecte/PoJie/PoJie/ruoyi-server/src/main/java/org/dromara/web/controller/CaptchaController.java#L112-L121)
- **短信验证码**`GET /resource/sms/code?phonenumber={phonenumber}`
- 限流:60秒内最多1次(按手机号)
- **代码路径**[CaptchaController.smsCode](file:///Users/lihaha/Documents/Projecte/PoJie/PoJie/ruoyi-server/src/main/java/org/dromara/web/controller/CaptchaController.java#L59-L76)
- **邮箱验证码**`GET /resource/email/code?email={email}`
- 限流:60秒内最多1次(按邮箱)
- **代码路径**[CaptchaController.emailCode](file:///Users/lihaha/Documents/Projecte/PoJie/PoJie/ruoyi-server/src/main/java/org/dromara/web/controller/CaptchaController.java#L83-L90)
#### 管理员绑定微信(建议)
- **生成绑定二维码**`POST /wx/mp/qrcode/{appid}/forever?sceneStr=sys_user:{userId}`
- 生成永久二维码,scene_str = sys_user:{userId}
- **获取二维码URL**`GET /wx/mp/qrcode/{appid}/url?ticket={ticket}`
- 根据ticket获取二维码图片URL
- **事件回调**`WxMpPortalController` 处理 `SCAN/SUBSCRIBE` 事件并完成绑定
- **代码路径**[WxMpPortalController](file:///Users/lihaha/Documents/Projecte/PoJie/PoJie/ruoyi-modules/ruoyi-mp/src/main/java/org/dromara/mp/controller/WxMpPortalController.java)
### 5.2 会话与权限规范
- Token 名称:`Authorization`(统一)。
- 并发策略:`is-concurrent=true` 支持多设备,按需要设置 `deviceType`。
- 登录态隔离:Sys 与 App 使用不同 LoginId 前缀与独立会话空间。
- 鉴权方式:Sys 采用注解鉴权(`@SaCheckPermission` 等);App 采用资源级鉴权(业务层校验 `userId` 所属资源)。
### 5.3 错误码与处理
- `401_BIND_REQUIRED`:微信授权成功但未绑定手机号,引导前端跳转绑定流程。
- `403_UPDATE_PWD`:Sys 账号密码超期未改,拦截除改密外所有接口。
- `403_INFO_INCOMPLETE`:App 用户信息未补全,仅放行资料完善接口。
### 5.4 约束与约定
- 不混用 Sys 与 App 的用户体系与权限模型。
- 微信授权优先使用 `unionId` 进行跨应用识别;若缺失则降级使用 `openId`。
- 新增登录方式遵循 `{grantType}AppAuthStrategy` 命名与策略路由约定。
### 5.5 App 角色与关联关系
- 表结构与关系:
- 用户表:`app_user`,参见 [ry_app.sql:app_user](file:///Users/lihaha/Documents/Projecte/PoJie/PoJie/script/sql/ry_app.sql#L6-L27)
- 角色表:`app_role`(角色键如 `app_user`、`app_vip`),参见 [ry_app.sql:app_role](file:///Users/lihaha/Documents/Projecte/PoJie/PoJie/script/sql/ry_app.sql#L35-L53)
- 关联表:`app_user_role`(多对多关联),参见 [ry_app.sql:app_user_role](file:///Users/lihaha/Documents/Projecte/PoJie/PoJie/script/sql/ry_app.sql#L56-L64)
- 规范说明:
- App 端角色用于业务权益与标签管理(如普通用户、VIP),不等同于 Sys 端的 RBAC 功能权限。
- 业务层根据 `role_key`(如 `app_vip`)判断权益与展示(价格、特权、活动资格等),避免与后台菜单/按钮权限混用。
- 登录后构建的 `AppLoginUser` 可加载角色集合用于业务判定;权限校验仍以资源归属为主(基于 `userId`)。
- 第三方授权表:
- `app_social_auth` 用于存储平台标识(`platform`/`platform_uid`)与微信 `open_id`/`union_id`,参见 [ry_app.sql:app_social_auth](file:///Users/lihaha/Documents/Projecte/PoJie/PoJie/script/sql/ry_app.sql#L67-L85)
- App 微信登录优先使用 `union_id` 进行账号打通;若缺失则降级使用 `open_id`。
### 5.6 调用实例(curl
- Sys 密码登录(grantType=password):
```bash
curl -sS -X POST "http://localhost:8080/auth/login" \
-H "Content-Type: application/json" \
-d '{
"clientId": "e5cd7e4891bf95d1d19206ce24a7b32e",
"grantType": "password",
"username": "admin",
"password": "admin123",
"code": "a1b2",
"uuid": "captcha-uuid"
}'
```
- Sys 短信登录(grantType=sms):
```bash
curl -sS -X POST "http://localhost:8080/auth/login" \
-H "Content-Type: application/json" \
-d '{
"clientId": "e5cd7e4891bf95d1d19206ce24a7b32e",
"grantType": "sms",
"phonenumber": "13800000000",
"smsCode": "123456"
}'
```
- Sys 邮箱登录(grantType=email):
```bash
curl -sS -X POST "http://localhost:8080/auth/login" \
-H "Content-Type: application/json" \
-d '{
"clientId": "e5cd7e4891bf95d1d19206ce24a7b32e",
"grantType": "email",
"email": "admin@example.com",
"emailCode": "654321"
}'
```
- Sys 第三方登录(grantType=socialsource∈{github,gitee,wechat_open,wechat_mp…}):
```bash
curl -sS -X POST "http://localhost:8080/auth/login" \
-H "Content-Type: application/json" \
-d '{
"clientId": "e5cd7e4891bf95d1d19206ce24a7b32e",
"grantType": "social",
"source": "github",
"socialCode": "oauth-code",
"socialState": "state-123"
}'
```
- App 密码登录(grantType=app_password):
```bash
curl -sS -X POST "http://localhost:8080/app/auth/login" \
-H "Content-Type: application/json" \
-d '{
"clientId": "428a8310cd442757ae699df5d894f051",
"grantType": "app_password",
"username": "appuser",
"password": "admin123"
}'
```
- App 短信登录(grantType=sms):
```bash
curl -sS -X POST "http://localhost:8080/app/auth/login" \
-H "Content-Type: application/json" \
-d '{
"clientId": "428a8310cd442757ae699df5d894f051",
"grantType": "sms",
"phonenumber": "13800000000",
"smsCode": "123456"
}'
```
- App 邮箱登录(grantType=email):
```bash
curl -sS -X POST "http://localhost:8080/app/auth/login" \
-H "Content-Type: application/json" \
-d '{
"clientId": "428a8310cd442757ae699df5d894f051",
"grantType": "email",
"email": "user@example.com",
"emailCode": "654321"
}'
```
- App 第三方登录(grantType=socialsource∈{github,gitee,wechat_open…}):
```bash
curl -sS -X POST "http://localhost:8080/app/auth/login" \
-H "Content-Type: application/json" \
-d '{
"clientId": "428a8310cd442757ae699df5d894f051",
"grantType": "social",
"source": "gitee",
"socialCode": "oauth-code",
"socialState": "state-xyz"
}'
```
- App 微信公众号登录(grantType=wechat_mp,前端已拿到 code 与 state):
```bash
curl -sS -X POST "http://localhost:8080/app/auth/login" \
-H "Content-Type: application/json" \
-d '{
"clientId": "428a8310cd442757ae699df5d894f051",
"grantType": "wechat_mp",
"socialCode": "wx-oauth-code",
"socialState": "state-123"
}'
```
- App 微信开放平台登录(grantType=wechat_open):
```bash
curl -sS -X POST "http://localhost:8080/app/auth/login" \
-H "Content-Type: application/json" \
-d '{
"clientId": "428a8310cd442757ae699df5d894f051",
"grantType": "wechat_open",
"socialCode": "wx-open-code",
"socialState": "state-456"
}'
```
- App 微信小程序登录(grantType=wechat_miniprogram):
```bash
curl -sS -X POST "http://localhost:8080/app/auth/login" \
-H "Content-Type: application/json" \
-d '{
"clientId": "428a8310cd442757ae699df5d894f051",
"grantType": "wechat_miniprogram",
"socialCode": "wx-mini-code",
"socialState": "state-789"
}'
```
- Sys 管理员绑定二维码(生成永久二维码 ticket 与 URL):
```bash
# 生成永久二维码,scene_str = sys_user:{userId}
curl -sS -X POST "http://localhost:8080/wx/mp/qrcode/{appid}/forever" \
-d "sceneStr=sys_user:1"
# 根据 ticket 获取二维码 URL
curl -sS -X GET "http://localhost:8080/wx/mp/qrcode/{appid}/url" \
--data-urlencode "ticket=YOUR_TICKET"
```
- 获取公众号配置:
```bash
curl -sS "http://localhost:8080/wx/mp/portal/{appid}/config"
```
- App 用户信息补全白名单接口示例(占位):
```bash
# 获取个人信息
curl -sS "http://localhost:8080/app/user/profile" -H "Authorization: Bearer YOUR_TOKEN"
# 绑定手机号
curl -sS -X POST "http://localhost:8080/app/user/bind" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_TOKEN" \
-d '{ "phone": "13800000000", "smsCode": "123456" }'
```
- Sys 退出登录:
```bash
curl -sS -X POST "http://localhost:8080/auth/logout" \
-H "Authorization: Bearer YOUR_TOKEN"
```
- App 退出登录:
```bash
curl -sS -X POST "http://localhost:8080/app/auth/logout" \
-H "Authorization: Bearer YOUR_TOKEN"
```
- Sys 用户注册:
```bash
curl -sS -X POST "http://localhost:8080/auth/register" \
-H "Content-Type: application/json" \
-d '{
"username": "newuser",
"password": "password123",
"userType": "sys_user",
"code": "a1b2",
"uuid": "captcha-uuid"
}'
```
- App 用户注册:
```bash
curl -sS -X POST "http://localhost:8080/app/auth/register" \
-H "Content-Type: application/json" \
-d '{
"username": "appuser",
"password": "password123"
}'
```
- 获取图形验证码:
```bash
curl -sS "http://localhost:8080/auth/code"
# 返回: {"code":200,"data":{"uuid":"xxx","img":"data:image/png;base64,...","captchaEnabled":true}}
```
- 获取短信验证码:
```bash
curl -sS "http://localhost:8080/resource/sms/code?phonenumber=13800000000"
```
- 获取邮箱验证码:
```bash
curl -sS "http://localhost:8080/resource/email/code?email=user@example.com"
```
- 获取App配置:
```bash
curl -sS "http://localhost:8080/app/auth/config"
# 返回: {"code":200,"data":{"registerEnabled":true}}
```
- Sys 获取第三方绑定URL
```bash
curl -sS "http://localhost:8080/auth/binding/github?domain=http://localhost:8080"
# 返回: {"code":200,"data":"https://github.com/login/oauth/authorize?..."}
```
- Sys 第三方绑定回调:
```bash
curl -sS -X POST "http://localhost:8080/auth/social/callback" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_TOKEN" \
-d '{
"source": "github",
"socialCode": "oauth-code",
"socialState": "state-123"
}'
```
- Sys 取消第三方绑定:
```bash
curl -sS -X DELETE "http://localhost:8080/auth/unlock/1" \
-H "Authorization: Bearer YOUR_TOKEN"
```
---
## 6. App 会话管理 API
- 基础路径:`/app/session`
- 鉴权:登录态(Sa-Token
### 6.1 接口列表
- `GET /app/session/active` 获取当前用户活跃会话列表
- `POST /app/session/terminate` 终止指定会话(参数:`sessionId`
- `POST /app/session/heartbeat` 会话续期(参数:`sessionId`,默认延长至 30 天)
- `GET /app/session/sse` 订阅会话事件(SSE),事件名:`session`,数据格式:`<TYPE>:<SESSION_ID>`
### 6.2 会话数据结构(AppSession
- `sessionId` 会话IDtoken值)
- `userId` 用户ID
- `deviceType` 设备类型(Web/iOS/Android/Desktop
- `deviceId` 设备标识(`X-Device-Id` 或生成)
- `userAgent` UA 字符串
- `ip` 登录IP
- `location` 地理位置(预留)
- `loginAt` 登录时间戳(毫秒)
- `expireAt` 过期时间戳(毫秒)
- `active` 活跃状态
- `token` 令牌原文
### 6.3 存储键规范
- 索引:`APP:SESS_INDEX:{userId}`
- 会话:`APP:SESS:{userId}:{sessionId}`TTL 与 token 同步)
- 事件通道:`APP:SESS_EVT:{userId}`
### 6.4 调用示例(curl
- 获取活跃会话:
```bash
curl -sS "http://localhost:8080/app/session/active" \
-H "Authorization: Bearer YOUR_TOKEN"
```
- 终止指定会话:
```bash
curl -sS -X POST "http://localhost:8080/app/session/terminate" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_TOKEN" \
-d '{ "sessionId": "TOKEN_VALUE_TO_TERMINATE" }'
```
- 会话续期(心跳):
```bash
curl -sS -X POST "http://localhost:8080/app/session/heartbeat" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_TOKEN" \
-d '{ "sessionId": "CURRENT_TOKEN_VALUE" }'
```
- 订阅会话事件(SSE):
```bash
curl -sS "http://localhost:8080/app/session/sse" \
-H "Authorization: Bearer YOUR_TOKEN"
```
### 6.5 优化建议
- 统一设备标识头 `X-Device-Id`,策略层在登录时读取并写入会话,便于同账号多设备管理。
- 事件命名与负载标准化:`<TYPE>:<SESSION_ID>`TYPE ∈ {login, logout, heartbeat, terminate})。
- TTL 与 Sa-Token 同步:确保 `APP:SESS:{userId}:{sessionId}` 的过期时间与 Token 过期保持一致,避免“僵尸会话”。
---
## 7. Sys 在线用户管理 API
- 基础路径:`/monitor/online`
- 鉴权:登录态(Sa-Token),需要权限 `monitor:online:*`
### 7.1 接口列表
- `GET /monitor/online/list` 获取在线用户监控列表(支持按IP、用户名筛选)
- `GET /monitor/online` 获取当前用户登录的在线设备列表
- `DELETE /monitor/online/{tokenId}` 强退指定用户(需要权限 `monitor:online:forceLogout`
- `DELETE /monitor/online/myself/{tokenId}` 强退当前用户的指定设备
### 7.2 在线用户数据结构(SysUserOnline
- `tokenId` 会话编号(Token值)
- `userName` 用户名称
- `deptName` 部门名称
- `clientKey` 客户端标识
- `deviceType` 设备类型
- `ipaddr` 登录IP地址
- `loginLocation` 登录地点
- `browser` 浏览器类型
- `os` 操作系统
- `loginTime` 登录时间(时间戳,毫秒)
### 7.3 调用示例(curl
- 获取在线用户列表:
```bash
curl -sS "http://localhost:8080/monitor/online/list?ipaddr=127.0.0.1&userName=admin" \
-H "Authorization: Bearer YOUR_TOKEN"
```
- 获取当前用户在线设备:
```bash
curl -sS "http://localhost:8080/monitor/online" \
-H "Authorization: Bearer YOUR_TOKEN"
```
- 强退指定用户:
```bash
curl -sS -X DELETE "http://localhost:8080/monitor/online/TOKEN_VALUE" \
-H "Authorization: Bearer YOUR_TOKEN"
```
- 强退当前用户的指定设备:
```bash
curl -sS -X DELETE "http://localhost:8080/monitor/online/myself/TOKEN_VALUE" \
-H "Authorization: Bearer YOUR_TOKEN"
```
- **代码路径**[SysUserOnlineController](file:///Users/lihaha/Documents/Projecte/PoJie/PoJie/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/monitor/SysUserOnlineController.java)
---
## 8. Sys 登录日志管理 API
- 基础路径:`/monitor/logininfor`
- 鉴权:登录态(Sa-Token),需要权限 `monitor:logininfor:*`
### 8.1 接口列表
- `GET /monitor/logininfor/list` 获取系统访问记录列表(分页,支持按IP、状态、用户名、时间范围筛选)
- `POST /monitor/logininfor/export` 导出系统访问记录列表(需要权限 `monitor:logininfor:export`
- `DELETE /monitor/logininfor/{infoIds}` 批量删除登录日志(需要权限 `monitor:logininfor:remove`
- `DELETE /monitor/logininfor/clean` 清理系统访问记录(需要权限 `monitor:logininfor:remove`
- `GET /monitor/logininfor/unlock/{userName}` 解锁指定用户的登录锁定(需要权限 `monitor:logininfor:unlock`
### 8.2 登录日志数据结构(SysLogininfor
- `infoId` 日志ID
- `userName` 用户账号
- `clientKey` 客户端标识
- `deviceType` 设备类型
- `status` 登录状态(0成功 1失败)
- `ipaddr` 登录IP地址
- `loginLocation` 登录地点
- `browser` 浏览器类型
- `os` 操作系统
- `msg` 提示消息
- `loginTime` 访问时间
### 8.3 调用示例(curl
- 获取登录日志列表:
```bash
curl -sS "http://localhost:8080/monitor/logininfor/list?ipaddr=127.0.0.1&status=0&userName=admin&beginTime=2024-01-01&endTime=2024-12-31&pageNum=1&pageSize=10" \
-H "Authorization: Bearer YOUR_TOKEN"
```
- 导出登录日志:
```bash
curl -sS -X POST "http://localhost:8080/monitor/logininfor/export" \
-H "Authorization: Bearer YOUR_TOKEN" \
-o logininfor.xlsx
```
- 批量删除登录日志:
```bash
curl -sS -X DELETE "http://localhost:8080/monitor/logininfor/1,2,3" \
-H "Authorization: Bearer YOUR_TOKEN"
```
- 清理登录日志:
```bash
curl -sS -X DELETE "http://localhost:8080/monitor/logininfor/clean" \
-H "Authorization: Bearer YOUR_TOKEN"
```
- 解锁用户登录:
```bash
curl -sS "http://localhost:8080/monitor/logininfor/unlock/admin" \
-H "Authorization: Bearer YOUR_TOKEN"
```
- **代码路径**[SysLogininforController](file:///Users/lihaha/Documents/Projecte/PoJie/PoJie/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/monitor/SysLogininforController.java)
---
## 9. 相关代码路径参考
### 9.1 核心控制器
- **Sys登录控制器**[AuthController](file:///Users/lihaha/Documents/Projecte/PoJie/PoJie/ruoyi-server/src/main/java/org/dromara/web/controller/AuthController.java)
- **App登录控制器**[AppAuthController](file:///Users/lihaha/Documents/Projecte/PoJie/PoJie/ruoyi-server/src/main/java/org/dromara/app/controller/AppAuthController.java)
- **验证码控制器**[CaptchaController](file:///Users/lihaha/Documents/Projecte/PoJie/PoJie/ruoyi-server/src/main/java/org/dromara/web/controller/CaptchaController.java)
### 9.2 核心服务
- **Sys登录服务**[SysLoginService](file:///Users/lihaha/Documents/Projecte/PoJie/PoJie/ruoyi-server/src/main/java/org/dromara/web/service/SysLoginService.java)
- **App登录服务**[AppLoginService](file:///Users/lihaha/Documents/Projecte/PoJie/PoJie/ruoyi-server/src/main/java/org/dromara/app/service/AppLoginService.java)
- **Sys注册服务**[SysRegisterService](file:///Users/lihaha/Documents/Projecte/PoJie/PoJie/ruoyi-server/src/main/java/org/dromara/web/service/SysRegisterService.java)
### 9.3 登录策略
- **Sys策略接口**[IAuthStrategy](file:///Users/lihaha/Documents/Projecte/PoJie/PoJie/ruoyi-server/src/main/java/org/dromara/web/service/IAuthStrategy.java)
- **App策略接口**[IAppAuthStrategy](file:///Users/lihaha/Documents/Projecte/PoJie/PoJie/ruoyi-server/src/main/java/org/dromara/app/service/IAppAuthStrategy.java)
- **密码策略**[PasswordAuthStrategy](file:///Users/lihaha/Documents/Projecte/PoJie/PoJie/ruoyi-server/src/main/java/org/dromara/web/service/impl/PasswordAuthStrategy.java), [AppPasswordAuthStrategy](file:///Users/lihaha/Documents/Projecte/PoJie/PoJie/ruoyi-server/src/main/java/org/dromara/app/service/impl/AppPasswordAuthStrategy.java)
- **短信策略**[SmsAuthStrategy](file:///Users/lihaha/Documents/Projecte/PoJie/PoJie/ruoyi-server/src/main/java/org/dromara/web/service/impl/SmsAuthStrategy.java), [AppSmsAuthStrategy](file:///Users/lihaha/Documents/Projecte/PoJie/PoJie/ruoyi-server/src/main/java/org/dromara/app/service/impl/AppSmsAuthStrategy.java)
- **邮箱策略**[EmailAuthStrategy](file:///Users/lihaha/Documents/Projecte/PoJie/PoJie/ruoyi-server/src/main/java/org/dromara/web/service/impl/EmailAuthStrategy.java), [AppEmailAuthStrategy](file:///Users/lihaha/Documents/Projecte/PoJie/PoJie/ruoyi-server/src/main/java/org/dromara/app/service/impl/AppEmailAuthStrategy.java)
- **第三方策略**[SocialAuthStrategy](file:///Users/lihaha/Documents/Projecte/PoJie/PoJie/ruoyi-server/src/main/java/org/dromara/web/service/impl/SocialAuthStrategy.java), [AppSocialAuthStrategy](file:///Users/lihaha/Documents/Projecte/PoJie/PoJie/ruoyi-server/src/main/java/org/dromara/app/service/impl/AppSocialAuthStrategy.java)
### 9.4 管理接口
- **在线用户管理**[SysUserOnlineController](file:///Users/lihaha/Documents/Projecte/PoJie/PoJie/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/monitor/SysUserOnlineController.java)
- **登录日志管理**[SysLogininforController](file:///Users/lihaha/Documents/Projecte/PoJie/PoJie/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/monitor/SysLogininforController.java)
- **登录日志服务**[SysLogininforService](file:///Users/lihaha/Documents/Projecte/PoJie/PoJie/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/SysLogininforService.java), [SysLogininforServiceImpl](file:///Users/lihaha/Documents/Projecte/PoJie/PoJie/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysLogininforServiceImpl.java)
---
所有代码与配置参考项目既有实现与路径,确保可在 IDE 中点击跳转进行联查与验证。