- Add deploy.sh for automated Docker build and push to private registry - Lowercase Docker image name to comply with registry requirements - Update README with concrete Docker run examples and configuration
图书管理系统
一个基于 Spring Boot + Kotlin + MyBatis-Plus 的后端图书管理系统,提供图书管理、用户认证、借阅归还等核心功能。项目注重安全性、可审计性,等保三级审计日志开箱即用。
功能
- 认证与授权 — JWT 无状态登录,Argon2 密码哈希,基于 AOP 的角色权限校验(admin / user),防用户枚举攻击
- 图书管理 — 搜索(书名 / 作者)、查看详情、新增 / 修改 / 删除 / 调整库存(管理员),书名 + 作者判重
- 借阅管理 — 借书 / 还书(自动扣减 / 恢复库存)、个人借阅记录、管理员可查看全部借阅及手动操作
- 审计日志 — 等保三级(GB/T 22239-2019 8.1.4.3),结构化审计日志,含用户标识、来源 IP、操作参数、结果摘要,支持持久化到文件
- 统一响应 — 所有接口返回
ApiResult<T>统一格式,业务码自动映射 HTTP 状态码 - OpenAPI 文档 — SpringDoc 自动生成,支持在线调试
技术栈
| 类别 | 技术 | 版本 | 说明 |
|---|---|---|---|
| 语言 | Kotlin | 2.2.21 | JVM 目标 |
| 框架 | Spring Boot | 4.0.6 | |
| ORM | MyBatis-Plus | 3.5.15 | 零 XML 配置,BaseMapper 通用 CRUD |
| 数据库 | MySQL | 8.0 | InnoDB,utf8mb4 |
| 认证 | jjwt (JSON Web Token) | 0.13.0 | HMAC-SHA256 签名 |
| 密码 | Argon2 (Spring Security Crypto) | 5.3+ | 抗 GPU/ASIC 暴力破解 |
| 协程 | kotlinx-coroutines | 1.10.2 | 并发查询用户 + 图书信息 |
| 文档 | SpringDoc OpenAPI | 3.0.3 | Swagger UI |
| AOP | AspectJ Weaver | — | 日志 / 审计 / 权限三切面 |
| 日志 | Logback + kotlin-logging | 7.0.0 | Janino 条件表达式,按天滚动 |
快速开始
1. 准备数据库
MySQL 8.0 中新建一个数据库(如 bookmgr),然后运行建表脚本:
mysql -u root -p bookmgr < bookmgr.schema.sql
脚本只建表,不插数据。默认用户由应用首次启动时自动创建。
2. 配置环境变量
生产环境通过环境变量注入配置:
export DB_DRIVER=com.mysql.cj.jdbc.Driver
export DB_TYPE=mysql
export DB_URL=localhost
export DB_PORT=3306
export DB_NAME=bookmgr
export DB_USER=root
export DB_PASSWORD=your-password
export JWT_SECRET=your-secret-at-least-32-chars
export JWT_EXPIRATION_TIME=86400000 # 可选,默认 24 小时,单位毫秒
export LOG_PATH=/var/log/bookmgr # 可选,不设置则不写日志文件
export LOG_EXPORT_AUDIT=true # 可选,审计日志持久化,默认开启
export LOG_EXPORT_RUNTIME=false # 可选,运行日志持久化,默认关闭
export LOG_LEVEL=INFO # 可选,包级别日志级别,默认 INFO
| 变量 | 必填 | 说明 |
|---|---|---|
DB_DRIVER |
是 | 驱动类名 |
DB_TYPE |
是 | 数据库类型(mysql) |
DB_URL |
是 | 数据库地址 |
DB_PORT |
是 | 数据库端口 |
DB_NAME |
是 | 数据库名 |
DB_USER |
是 | 数据库用户 |
DB_PASSWORD |
是 | 数据库密码 |
JWT_SECRET |
强烈建议 | 不设置则每次启动随机生成,已签发 token 全部失效 |
JWT_EXPIRATION_TIME |
否 | token 有效期(毫秒),默认 86400000(24 小时) |
3. 运行
./gradlew bootRun
4. 默认用户
应用首次启动时自动创建以下用户(幂等,已存在则跳过):
| 用户名 | 密码 | 角色 |
|---|---|---|
admin |
admin |
管理员 |
user01 |
user01 |
普通用户 |
user02 |
user02 |
普通用户 |
注意:预置用户当前硬编码在
InitUserRunner中。未来计划分三步演进:硬编码 → 配置文件 → 前端初始化向导。生产部署后请第一时间修改密码。
开发指南
IDEA 运行配置
- 复制
src/main/resources/application.yaml为application-dev.yaml,修改数据库连接等本地配置 - IDEA → Run Configuration → Active profiles 填写
dev
- 启动即可
示例 application-dev.yaml:
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/bookmgr
username: root
password: your-password
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.commons.JakartaCommonsLoggingImpl
logging:
level:
com.msksbr.bookmgr: DEBUG
export:
path: ./log
runtime-enabled: true
jwt:
expiration: 86400000
springdoc:
swagger-ui:
enabled: true
api-docs:
enabled: true
Swagger 文档
开发环境启动后访问:http://localhost:8080/swagger-ui/index.html
生产环境默认关闭,防止 API 文档暴露。
API 概览
公开接口:
POST /api/auth/login — 登录
POST /api/auth/logout — 登出
GET /api/books/search — 搜索图书
GET /api/books/getone — 图书详情
GET /api/books/getall — 所有图书
普通用户(需 JWT + user 角色):
GET /api/borrows/getall — 我的借阅
GET /api/borrows/search — 搜索我的借阅
GET /api/borrows/getone — 借阅详情
POST /api/borrows/borrowbook — 借书
POST /api/borrows/returnbook — 还书
管理员(需 JWT + admin 角色):
POST /api/admin/books/add — 新增图书
POST /api/admin/books/update — 修改图书
POST /api/admin/books/delete — 删除图书
POST /api/admin/books/update-stock — 调整库存
GET /api/admin/borrows/search — 搜索借阅
GET /api/admin/borrows/getone — 借阅详情
GET /api/admin/borrows/getall — 全部借阅
POST /api/admin/borrows/borrowbook — 手动借书
POST /api/admin/borrows/returnbook — 手动还书
请求示例:
# 登录获取 token
curl -X POST http://localhost:8080/api/auth/login \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":"admin"}'
# 搜索图书
curl "http://localhost:8080/api/books/search?query=西游记"
# 借书
curl -X POST "http://localhost:8080/api/borrows/borrowbook?bookId=1" \
-H "Authorization: Bearer <token>"
项目结构
src/main/kotlin/com/msksbr/bookmgr/
├── controller/ # 控制器 — 接口入口
├── service/ # 服务接口
│ └── impl/ # 服务实现 — 业务逻辑
├── mapper/ # MyBatis-Plus 映射器 — 数据访问
├── entity/ # 实体 — 表映射
├── dto/ # 请求体 DTO
├── vo/ # 响应 VO
│ └── borrow/ # 借阅相关 VO
├── config/ # 配置 — JWT / 密码 / AOP 切面 / 异常处理 / OpenAPI
├── annotation/ # 自定义注解 — @RequireRole
├── runner/ # 启动任务 — InitUserRunner
├── script/ # 扩展 — log / audit Logger 快捷获取
└── template/ # ApiResult<T> 统一响应模板
部署
Java 直接运行
./gradlew bootJar
java -jar build/libs/bookMgr-0.1.jar
bootJar会自动排除application-dev.yaml。
Docker
镜像基于 bellsoft/liberica-runtime-container:jre-21-slim-musl,JVM 参数 -Xmx512m -Dfile.encoding=UTF-8,暴露 8080 端口。
# 拉取镜像
docker pull git.msksbr.com/msksbr/bookmgr:v0.1
# 运行
docker run -d \
--name bookmgr \
-p 8080:8080 \
-e DB_DRIVER=com.mysql.cj.jdbc.Driver \
-e DB_TYPE=mysql \
-e DB_URL=your-db-host \
-e DB_PORT=3306 \
-e DB_NAME=bookmgr \
-e DB_USER=root \
-e DB_PASSWORD=your-password \
-e JWT_SECRET=your-secret \
-e LOG_PATH=/var/log/bookmgr \
git.msksbr.com/msksbr/bookmgr:v0.1
镜像托管于私有 Gitea 仓库:git.msksbr.com/msksbr/bookMgr
Docker Compose
Compose 文件待补充。注意生产环境应执行 bookmgr.schema.sql(仅建表,不含种子数据),用户由应用初始化。
审计日志
满足等保三级要求的结构化审计日志,默认输出到控制台。配置 LOG_PATH 后自动持久化到文件:
$LOG_PATH/
├── audit/
│ ├── audit.log # 当天审计日志
│ └── audit.2026-05-23.0.gz # 历史归档(滚动策略:按天 + 100MB,保留 365 天,上限 20GB)
└── runtime/
├── runtime.log # 当天运行日志(需 LOG_EXPORT_RUNTIME=true)
└── runtime.2026-05-23.0.gz
审计日志记录字段:事件类型(CTRL / SVC)、用户名、用户 ID、角色、来源 IP、User-Agent、HTTP 方法 + 路径、操作参数(敏感字段自动掩码)、返回状态码、操作对象 ID、耗时。
安全特性
- 密码使用 Argon2 哈希存储,即使数据库泄露也无法还原
- 登录失败时对齐响应时间(dummy hash),防止基于延时的用户枚举
- 敏感参数(password / token / secret / authorization)在审计日志中自动掩码为
*** - JWT 密钥支持环境变量注入,不配置则每次启动随机生成
- 全局异常捕获,不向客户端泄露堆栈信息
- 生产环境默认关闭 Swagger 文档
声明
本项目基于 MIT 协议开源。本软件无任何销售渠道,不收取费用。请遵守开源协议合法使用。
作者
- 个人主页:msksbr.com
- 项目仓库:git.msksbr.com/msksbr/bookMgr
