# 授权管理系统 **Repository Path**: small-xch6/authorization ## Basic Information - **Project Name**: 授权管理系统 - **Description**: 基于 RuoYi-Vue-Plus 4.8.2 与 Xbatis ORM 框架构建的后台管理系统,内置一套完整的 Jar 授权系统(客户管理 / 授权证书 / 授权日志 / 客户端 SDK)。 - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-08-29 - **Last Updated**: 2026-09-11 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # RuoYi-Plus-Xbatis 基于 [RuoYi-Vue-Plus](https://gitee.com/dromara/RuoYi-Vue-Plus) 4.8.2 与 [Xbatis](https://gitee.com/xbatis/xbatis) ORM 框架构建的后台管理系统,并内置一套完整的 **Jar 授权系统**(客户管理 / 授权证书 / 授权日志 / 项目管理 / 项目版本 / 客户端 SDK)。 > - 基础框架(本仓库):https://gitee.com/small-xch6/authorization.git > - ORM 框架(Xbatis):https://gitee.com/xbatis/xbatis --- ## 一、可视化概览 ```mermaid flowchart LR Biz["业务应用"] --> SDK["license-sdk
LicenseGuard
LicenseClient"] SDK -->|"在线校验 / 心跳 / 下线"| API["授权服务端
checkOnline
offline
publicKey
reportOffline"] UI["授权管理后台
Vue2 + Element UI"] -->|"管理操作"| API API --> SVC["业务层
客户 / 证书 / 日志 / 项目 / 版本 / 统计"] SVC --> DB[("MySQL
license 表")] SVC --> RDS[("Redis
实例心跳 / 防多开")] SVC --> OSS[("OSS
版本发布包")] ``` --- ## 二、软件架构图 ```mermaid flowchart TB subgraph P["表现层"] UI2["授权管理页面"] SDK2["license-sdk 客户端"] end subgraph C["接口层"] C1["客户 Controller"] C2["证书 Controller"] C3["日志 Controller"] C4["功能模块 Controller"] C5["项目 Controller"] C6["版本 Controller"] end subgraph S["业务层"] S1["客户 Service"] S2["证书 Service"] S3["日志 Service"] S4["功能模块 Service"] S5["项目 Service
按项目 RSA 密钥"] S6["版本 Service
OSS 上传下载"] TK["到期预警任务"] end subgraph D["数据层"] MP["Mapper + Xbatis QueryChain"] end subgraph I["基础设施"] MYSQL[("MySQL")] REDIS[("Redis")] XXL["XXL-Job"] SAT["Sa-Token"] end UI2 --> C1 UI2 --> C2 UI2 --> C3 UI2 --> C4 UI2 --> C5 UI2 --> C6 SDK2 -->|"HTTP 校验"| C2 SDK2 -->|"获取项目公钥"| C5 C1 --> S1 C2 --> S2 C3 --> S3 C4 --> S4 C5 --> S5 C6 --> S6 S1 --> MP S2 --> MP S3 --> MP S4 --> MP S5 --> MP S6 --> MP MP --> MYSQL S2 --> REDIS S6 --> OSS2[("OSS")] XXL --> TK TK --> S2 SAT -.->|"鉴权"| C1 SAT -.->|"鉴权"| C2 SAT -.->|"鉴权"| C3 ``` --- ## 三、功能清单 ### 功能图 ```mermaid flowchart TB LIC["Jar 授权系统"] LIC --> MGR["授权管理后台"] LIC --> SDK3["客户端 SDK"] LIC --> BASE["基础设施"] MGR --> F1["客户管理"] MGR --> F2["功能模块管理"] MGR --> F3["授权证书"] MGR --> F4["授权日志"] MGR --> F5["统计看板"] SDK3 --> F6["机器码采集"] SDK3 --> F7["在线校验"] SDK3 --> F8["离线校验"] SDK3 --> F9["心跳 / 防多开"] SDK3 --> F10["功能权限"] BASE --> F11[("MySQL")] BASE --> F12[("Redis")] BASE --> F13["XXL-Job 到期预警"] ``` ### 功能清单表格 | 模块 | 功能 | 说明 | 权限标识 | | --- | --- | --- | --- | | 客户管理 | 客户 CRUD / 启停 | 维护授权客户信息,供授权证书选择 | `license:customer:*` | | 项目管理 | 项目 CRUD / 启停 | 多产品支持:每项目独立编码 + 独立 RSA 密钥对;停用后其下授权立即失效 | `license:project:*` | | 项目管理 | 项目公钥 | 按项目编码提供公钥,供客户端 SDK 离线验签(无需登录) | 无 | | 项目版本 | 上传发布包 | Jar/zip 上传至 OSS,录入版本号/更新说明,**上传即自动设为最新版** | `license:project:add` | | 项目版本 | 版本列表 / 下载 | 按项目分页查看,支持下载版本包 | `license:project:list` | | 项目版本 | 最新版本查询 / 下载(SDK 升级) | 客户端 SDK 免登录查询项目最新可用版本;携带有效授权 Key 下载升级包 | 无需登录 | | 项目版本 | 启停 / 设为最新 / 删除 | 版本停用启用、手动设为最新(同项目仅一个最新)、删除联动 OSS 对象 | `license:project:edit/remove` | | 功能模块 | 功能点 CRUD / 启停 | 按项目隔离维护功能点字典(项目内编码唯一),授权证书多选 | `license:function:*` | | 授权证书 | 签发 / 编辑 / 吊销 | 机器绑定 / 通用授权码,绑定机器码、过期时间、最大实例数、功能权限,**强制归属项目** | `license:info:*` | | 授权证书 | 离线证书下载 | 按所属项目私钥 RSA 签名生成 `.license` 文件 | `license:info:download` | | 授权证书 | 在线校验 | SDK 上报校验:状态 / 过期 / 机器码 / 时间回拨 / 防多开 / **项目编码匹配**,**项目停用联动拦截** | 无需登录 | | 授权证书 | 统计看板 / 导出 | 授权数量统计(可按项目过滤)、Excel 导出 | `license:info:list/export` | | 授权日志 | 查询 / 删除 / 清空 | 在线 / 离线校验日志(可按项目筛选) | `license:log:*` | | 授权日志 | 离线结果上报 | SDK 本地离线校验后上报结果(无需登录) | 无 | | 定时任务 | 到期预警 | XXL-Job 扫描 30 天内到期 / 已过期授权并输出预警 | - | | 客户端 SDK | 机器码采集 | MAC + CPU + 主板 + 系统内核 混合 MD5 | - | | 客户端 SDK | 在线 / 离线 / 综合校验 | 在线优先,失败降级本地缓存 / 离线证书;支持 `projectCode` 多项目 | - | | 客户端 SDK | 心跳 / 防多开 / 功能权限 | 定时心跳上报、实例数限制、`hasFunction` 功能点判断 | - | | 客户端 SDK | 版本升级检查 / 升级包下载 | `checkUpgrade` 对比服务端最新版本号,`downloadUpgrade` 携带授权 Key 下载升级包 | - | ### 功能说明 **1. 授权管理后台** - **客户管理**:客户的新增、修改、删除、状态变更(启用/停用),以及供授权证书选择客户的下拉列表。 - **项目管理**:多软件产品管理。每个项目拥有独立项目编码与独立 RSA 密钥对(私钥仅服务端持有);提供项目级公钥接口供 SDK 离线验签;项目停用后其下所有授权在线校验立即失效;存在关联授权/版本时禁止删除。 - **项目版本管理**:按项目上传 Jar/zip 发布包至 OSS,维护版本号、更新说明、文件大小/MD5;上传即自动标记为最新版本(同项目仅保留一个"最新"标记);支持下载、停用/启用、手动设为最新、删除(同步删除 OSS 对象)。 - **功能模块管理**:按项目隔离维护可授权给客户的功能点字典(项目内功能编码唯一)。授权证书勾选功能模块时仅从所属项目的功能列表多选。 - **授权证书**: - 授权类型:机器绑定授权、通用授权码。 - 强制归属项目;绑定机器码白名单、过期时间(可设永久)、最大运行实例数、功能模块权限。 - 状态管理:正常、禁用、吊销。 - 下载离线 `.license` 证书(按所属项目私钥签名)、导出 Excel、统计看板(可按项目过滤)、实时在线状态与在线实例数展示。 - **授权日志**:在线/离线校验日志的查询(可按项目筛选)、删除、清空。 **2. 客户端 SDK(license-sdk)** - 机器指纹采集(MAC + CPU + 主板 + 系统内核,混合 MD5)。 - 在线校验、离线 `.license` 证书校验(RSA 验签)。 - 定时心跳上报、防多开(实例数限制)、本地缓存降级。 - 多项目支持:可配置 `projectCode`,自动获取项目级公钥。 - 功能权限判断(`hasFunction`)。 - 版本升级检查(`checkUpgrade`)与升级包下载(`downloadUpgrade`):免登录查询项目最新版本,携带有效授权 Key 下载升级包(机器绑定授权需本机机器码匹配)。 - 提供 `LicenseGuard` 一行式门面,零框架依赖,可被任意 Java 项目直接调用。 **3. 统计与预警** - 统计看板:授权总数、正常 / 禁用 / 吊销数量、机器绑定 / 通用授权码数量、已激活 / 已过期 / 即将到期数量。 - 到期预警定时任务:扫描 30 天内到期及已过期的正常授权并输出预警。 --- ## 四、技术栈 | 分类 | 技术 | | --- | --- | | 后端框架 | Spring Boot 2.7.18、RuoYi-Vue-Plus 4.8.2 | | ORM | Xbatis 1.10.0(基于 MyBatis 的强 ORM 化 DSL 框架) | | 权限认证 | Sa-Token | | 缓存 / 分布式 | Redis + Redisson | | 定时任务 | XXL-Job | | 前端 | Vue2 + Element UI | | 授权 SDK | 纯 JDK + Gson,无框架依赖 | --- ## 五、模块结构 ``` RuoYi-Plus-Xbatis ├── ruoyi # 主项目(授权系统后端 + 通用框架) ├── ruoyi-extend # 扩展模块 ├── license-sdk # 授权客户端 SDK(轻量,仅依赖 Gson) └── script/sql # 授权系统建表 + 菜单 + 字典 SQL ``` 授权模块核心包路径:`com.ruoyi.license`(controller / service / domain / core / task / mapper)。 ``` com.ruoyi.license ├── controller # 客户 / 证书 / 日志 / 功能 / 项目 / 版本 控制器 ├── service # 业务服务 + LicenseRsaManager 密钥管理 ├── domain # 实体(LicenseInfo / LicenseProject / LicenseProjectVersion 等) ├── mapper # Xbatis Mapper ├── core # 校验协议 / 加解密 / 常量 └── task # 到期预警定时任务 ``` --- ## 六、环境要求 - JDK 1.8+ - Maven 3.6+ - MySQL 8.0+ - Redis 5.0+ - Node.js(前端构建,可选) --- ## 七、快速开始(服务端部署) ### 1. 初始化数据库 先导入 RuoYi-Vue-Plus 的基础库(含 `sys_user`、`sys_menu` 等),再依次执行授权系统 SQL: ```sql -- 授权系统基础表 + 菜单 + 字典 source script/sql/license.sql; -- 项目管理与版本管理增量(建表 + 存量数据迁移到默认项目 + 菜单) source script/sql/license_project.sql; ``` `license.sql` 会创建授权基础表并写入菜单、字典: - `license_customer`:授权客户表 - `license_function`:授权功能模块表 - `license_info`:授权证书主表 - `license_log`:授权校验日志表 `license_project.sql` 为项目管理与版本管理增量脚本,包含: - `license_project`:授权项目表(独立 RSA 密钥对) - `license_project_version`:项目版本表(发布包存 OSS) - 为 `license_info` / `license_function` / `license_log` 增加 `project_id` 字段与索引 - 创建「默认项目」并将存量授权数据迁移归属 - 项目管理 / 项目版本菜单(`license:project:*` 权限) ### 2. 修改配置 编辑 `ruoyi/src/main/resources/application-dev.yml`: - **数据源**:`spring.datasource.dynamic.datasource.master` 下的 `url`、`username`、`password`。 - **Redis**:`spring.redis` 与 `redisson.singleServerConfig` 的连接信息。 > **大文件上传限制(版本包)**:服务端已内置处理,无需额外配置—— > > - `ruoyi/src/main/resources/application.yml` 中 `spring.servlet.multipart.max-file-size / max-request-size` 均为 `500MB`; > - Undertow 请求体上限已在 `UndertowConfig` 中放开(`MAX_ENTITY_SIZE = -1`,Spring Boot 2.7 下 `server.undertow.max-http-post-size` 配置项已失效,需通过代码设置)。 > > 若经 Nginx 反代部署,还需在 Nginx 中同步调大 `client_max_body_size`(如 `client_max_body_size 500m;`),否则上传大包会被 Nginx 拦截。 ### 3. 启动服务 ```bash # 后端 mvn clean package -DskipTests java -jar ruoyi/target/ruoyi.jar ``` 或直接在 IDE 中运行 `com.ruoyi.RuoYiApplication`。 默认后端地址:`http://localhost:8080`。 --- ## 八、授权 SDK 使用教程 `license-sdk` 仅依赖 Gson,HTTP 与加解密均为纯 JDK 实现,可直接作为 Maven 模块嵌入被授权项目,无需安装到本地仓库。 ### 1. 引入 SDK **方式一:作为 Maven 模块(推荐)** 在被授权项目的父 `pom.xml` 中声明该模块,或在业务模块中直接依赖: ```xml com.ruoyi license-sdk 4.8.2 ``` **方式二:打包为 Jar 后引入** ```bash cd license-sdk mvn clean install ``` ### 2. LicenseGuard 一行式门面 ```java import com.ruoyi.license.sdk.LicenseGuard; import com.ruoyi.license.sdk.LicenseResult; // 获取本机机器码(供授权方登记白名单) String machineCode = LicenseGuard.machineCode(); // 在线校验:不通过则抛出 LicenseException(适合 Spring 项目,让启动直接失败) LicenseResult result = LicenseGuard.verifyOrThrow("http://localhost:8080", "your-license-key"); // 在线校验:不通过则打印错误并退出进程(适合独立 Jar / 无框架项目) LicenseGuard.verifyOrExit("http://localhost:8080", "your-license-key"); // 离线校验:使用 .license 文件内容 + 服务端公钥,无需联网 LicenseResult offline = LicenseGuard.verifyOffline(licenseContent, publicKey, "your-license-key"); // 多项目场景:传入 projectCode,自动获取项目级公钥 LicenseResult multi = LicenseGuard.verifyOrThrow("http://localhost:8080", "your-license-key", "my-project"); ``` ### 3. LicenseClient 完整能力 ```java import com.ruoyi.license.sdk.LicenseClient; import com.ruoyi.license.sdk.LicenseResult; LicenseClient client = new LicenseClient("http://localhost:8080", "your-license-key"); // 综合校验:优先在线,网络不可用时降级到本地缓存 / 离线证书 LicenseResult result = client.check(); // 在线校验 LicenseResult online = client.checkOnline(); // 获取服务端 RSA 公钥(供离线验签) String publicKey = client.fetchPublicKey(); // 设置离线 .license 证书内容,用于在线不可用时降级 client.setLicenseContent(licenseContent); // 启动定时心跳(周期上报并刷新本地缓存),防多开由服务端实例数校验兜底 client.startHeartbeat(60); // 停止心跳 client.stopHeartbeat(); ``` 多项目(多产品)场景: ```java // 方式一:构造时指定项目编码 LicenseClient client = new LicenseClient("http://localhost:8080", "your-license-key", "my-project"); // 方式二:通过 setter 指定 client.setProjectCode("my-project"); // 获取该项目级 RSA 公钥(供离线验签);未设置 projectCode 时回退默认项目公钥 String publicKey = client.fetchPublicKey(); ``` > **项目编码匹配校验**:在线校验时,SDK 会把 `projectCode` 随请求上报,服务端会校验其与授权所属项目编码是否一致,**不匹配直接拒绝**(防止跨项目冒用授权)。因此 `projectCode` 必须填写授权所属项目的真实编码(未指定时回退默认项目 `default`)。 ### 4. 校验结果与功能权限 ```java LicenseResult result = client.check(); if (result.isSuccess()) { // 是否拥有指定功能模块权限(functions 含 all 视为拥有全部) boolean hasReport = result.hasFunction("report"); } ``` 功能模块编码由授权方在后台「功能模块管理」中维护,在「授权证书」创建/修改时从该列表多选要开放的功能点。勾选「全部」即 `functions` 含 `all`,此时任意 `hasFunction(xxx)` 均返回 `true`。 端到端流程: 1. 授权方在「功能模块管理」新增功能点,例如编码 `report`(报表)、`export`(导出)。 2. 授权方在「授权证书」中勾选要开放给该客户的功能模块(或选「全部」)。 3. 被授权方通过 `result.hasFunction("report")` 判断是否开放对应功能,未授权功能做隐藏 / 拦截。 > 提示:`functions` 为逗号分隔的编码串(`all` 为特殊值),在线校验与离线证书下发的字段一致,客户端无需区分。 ### 5. 授权校验流程 1. 授权方在后台创建授权证书,登记机器码白名单、过期时间、最大实例数、功能权限。 2. 被授权方调用 `LicenseGuard.machineCode()` 采集机器码,提供给授权方绑定。 3. 被授权方在启动时调用 `verifyOrThrow` / `verifyOrExit` 完成在线校验。 4. 可选:启动心跳持续上报,服务端据此判断在线状态与实例数;下载 `.license` 证书实现离线降级。 ### 6. 版本升级检查与升级包下载 SDK 提供版本升级能力:免登录查询项目最新版本并比较版本号,携带有效授权 Key 下载升级包。版本号比较规则见 `VersionUtil`(数字分段比较,兼容 `v` 前缀与 `-beta` 等后缀,如 `1.0.0-beta` < `1.0.0`)。 ```java import com.ruoyi.license.sdk.LicenseClient; import com.ruoyi.license.sdk.model.LicenseUpgradeInfo; LicenseClient client = new LicenseClient("http://localhost:8080", "your-license-key", "my-project"); // 1. 检查是否有可升级的新版本(currentVersion 为当前运行版本号) LicenseUpgradeInfo info = client.checkUpgrade("1.0.0"); if (info.isHasUpgrade()) { System.out.println("发现新版本: " + info.getLatestVersion()); System.out.println("更新说明: " + info.getReleaseNotes()); System.out.println("包大小: " + info.getFileSize() + " bytes"); // 2. 下载升级包到本地文件(父目录不存在时自动创建) client.downloadUpgrade("D:/upgrade/" + info.getFileName()); // 或下载到输出流:client.downloadUpgrade(outputStream); } else { System.out.println("当前已是最新版本: " + info.getLatestVersion()); } ``` `LicenseGuard` 静态门面(适合无框架 / 独立 Jar): ```java LicenseUpgradeInfo info = LicenseGuard.checkUpgrade("http://localhost:8080", "your-license-key", "my-project", "1.0.0"); File pkg = LicenseGuard.downloadUpgrade("http://localhost:8080", "your-license-key", "my-project", "D:/upgrade/version.jar"); ``` `LicenseUpgradeInfo` 字段说明: | 字段 | 含义 | | --- | --- | | `hasUpgrade` | 是否存在可升级的新版本(`currentVersion` 为空时恒为 `false`) | | `latestVersion` | 服务端最新版本号 | | `releaseNotes` | 更新说明 | | `fileName` / `fileSize` | 版本包原始文件名 / 大小(字节) | | `publishTime` | 发布时间 | > 说明:查询最新版接口无需登录;**下载升级包必须携带有效授权 Key**(机器绑定授权还需本机机器码与白名单匹配),下载失败会抛出 `LicenseException` / `IOException`。 ### 7. 实例下线上报(应用停止后立即下线) SDK 在发生在线校验或启动心跳后,会自动注册 **JVM 退出钩子**:应用进程正常退出(`Ctrl+C`、`System.exit`、Spring 容器关闭等)时,自动调用服务端 `/license/info/offline` 接口移除本实例,**后台在线状态立即变灰**,无需等待心跳超时。 ```java // 无需额外代码——只要调用过校验或 startHeartbeat,退出时自动上报 LicenseClient client = new LicenseClient(serverUrl, licenseKey, projectCode); client.check(); // 或 startHeartbeat(60) / verifyOrThrow(...) // 进程退出时自动上报下线 ``` 如需手动控制,可调用: ```java client.reportOffline(); // 主动上报下线(幂等,多次调用无副作用) ``` > **兜底机制**:若进程被强制杀死(`kill -9`)或崩溃,退出钩子无法执行,实例将在服务端心跳有效期(`INSTANCE_HEARTBEAT_SECONDS`,默认 **15 秒**)后自动过期下线。 --- ## 九、授权接口说明 | 接口 | 方法 | 说明 | 鉴权 | | --- | --- | --- | --- | | `/license/info/checkOnline` | POST | 在线授权校验(状态/过期/机器码/防多开/项目编码匹配,客户端调用) | 无需登录 | | `/license/info/offline` | POST | 实例下线上报(客户端退出时主动移除实例,立即下线) | 无需登录 | | `/license/info/publicKey` | GET | 获取 RSA 公钥(离线验签用) | 无需登录 | | `/license/log/reportOffline` | POST | 上报离线校验结果 | 无需登录 | | `/license/project/publicKey` | GET | 按项目编码获取项目公钥(离线验签用) | 无需登录 | | `/license/project/list` | GET | 项目分页列表 | `license:project:list` | | `/license/project/optionselect` | GET | 项目下拉(启用中) | `license:project:list` | | `/license/project/{id}` | GET | 项目详情 | `license:project:query` | | `/license/project` | POST/PUT | 新增(自动生成 RSA 密钥对)/ 修改项目 | `license:project:add/edit` | | `/license/project/{ids}` | DELETE | 删除项目(存在关联时拦截) | `license:project:remove` | | `/license/project/changeStatus` | PUT | 项目启用/停用 | `license:project:edit` | | `/license/project/version/list` | GET | 按项目分页查询版本 | `license:project:list` | | `/license/project/version/upload` | POST | 上传版本包(自动设为最新) | `license:project:add` | | `/license/project/version/download/{id}` | GET | 下载版本包 | `license:project:list` | | `/license/project/version/changeStatus` | PUT | 版本停用/启用 | `license:project:edit` | | `/license/project/version/setLatest/{id}` | PUT | 设为最新版 | `license:project:edit` | | `/license/project/version/latest` | GET | 查询项目最新可用版本(SDK 升级检查) | 无需登录 | | `/license/project/version/download/latest` | GET | 下载项目最新版本包(需携带有效授权 Key,机器绑定授权需匹配机器码) | 无需登录 | | `/license/project/version/{ids}` | DELETE | 删除版本(联动删除 OSS 对象) | `license:project:remove` | | `/license/info/download/{id}` | GET | 下载离线 `.license` 证书 | 需权限 | | `/license/info/statistics` | GET | 授权统计看板(可按项目过滤) | 需权限 | | `/license/info/export` | POST | 导出授权证书 Excel | 需权限 | | `/license/customer/*` | - | 客户管理 | 需权限 | | `/license/function/*` | - | 功能模块管理(含 `optionselect` 下拉,按项目过滤) | 需权限 | | `/license/log/*` | - | 授权日志管理(按项目筛选) | 需权限 | --- ## 十、定时任务 到期预警任务 `licenseExpireWarnHandler`(`com.ruoyi.license.task.LicenseExpireWarnTask`)扫描 30 天内到期及已过期的正常授权并输出预警。 在 XXL-Job 调度中心新增任务,`JobHandler` 填写 `licenseExpireWarnHandler`,设置执行周期即可。 --- ## 十一、相关链接 - 基础框架源码:https://gitee.com/small-xch6/authorization.git - ORM 框架 Xbatis:https://gitee.com/xbatis/xbatis - Xbatis 官方文档:https://xbatis.cn - RuoYi-Vue-Plus:https://gitee.com/dromara/RuoYi-Vue-Plus