# 登录模块综合开发指南(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`,数据格式:`:` ### 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 ∈ {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 中点击跳转进行联查与验证。