# 授权管理系统
**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