first commit
This commit is contained in:
@@ -0,0 +1,718 @@
|
||||
# 登录模块综合开发指南(LOGIN_COMPREHENSIVE_GUIDE)
|
||||
|
||||
版本:v1.1.0(2025-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 微信公众号整合(双端)
|
||||
- App:OAuth2 获取 `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=social,source∈{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=social,source∈{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` 会话ID(token值)
|
||||
- `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 中点击跳转进行联查与验证。
|
||||
Reference in New Issue
Block a user