# hertz-admin
**Repository Path**: outoftime/hertz-admin
## Basic Information
- **Project Name**: hertz-admin
- **Description**: https://github.com/gjing1st/hertz-admin.git
- **Primary Language**: Go
- **License**: Apache-2.0
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2026-09-30
- **Last Updated**: 2026-09-30
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# hertz-admin
**基于 CloudWeGo Hertz 的生产级 Go 后端项目脚手架**
分层架构 · 统一错误码 · 三级权限 · 国密加密 · 国产化数据库适配 · 一键部署
[](https://go.dev)
[](https://github.com/cloudwego/hertz)
[](https://gorm.io)
[](./LICENSE)
[](https://github.com/gjing1st/hertz-admin/pulls)
**中文文档** | [English](./README_EN.md)
---
## 📌 这是什么
一个**开箱即用的 Go 后端工程骨架**,不是又一个 demo。
它把后端项目从零搭建时要重复写的那些东西——分层结构、错误码体系、权限中间件、日志、配置、版本注入、容器化部署——全部固化下来。你 clone 下来改业务逻辑就行,不用再纠结目录怎么分、错误怎么返、权限怎么拦。
底层用字节跳动开源的 **Hertz**(当前 Go 生态性能最好的 HTTP 框架之一),工程布局遵循 **golang-standards/project-layout** 标准,并**内置国密 SM3/SM4 算法**,适配信创场景。
全部依赖已 **vendor 到仓库**,在完全离线的内网环境中无需代理、无需联网即可构建。
## ✨ 核心特性
| 特性 | 说明 |
|---|---|
| 🚀 **高性能底座** | CloudWeGo Hertz,基于 netpoll 的非阻塞 I/O |
| 📐 **标准分层** | `router → controller → service → store → model` 单向依赖,golang-standards 布局 |
| 🔢 **统一错误码** | 所有 error 收敛为可观测错误码,业务码与 HTTP 状态码分离 |
| 🔐 **三级权限模型** | 登录态 / 管理员 / 超级管理员,中间件按路由组注册 |
| 🛡️ **国密算法内置** | SM3、SM4(CBC/ECB/CFB/OFB)、SM4-GCM,密码以 HMAC-SM3 存储 |
| 🗄️ **多数据库支持** | MySQL / PostgreSQL / openGauss / 人大金仓 / 达梦 / SQLite / ClickHouse 适配就绪,默认仅启用 MySQL,按需开启 |
| 🔒 **登录安全** | 密码错误次数累计与锁定(防爆破)、完整性校验、密码有效期 |
| 📝 **结构化日志** | logrus + lumberjack,支持标准输出/文件、日志切割、调用者信息 |
| 🏷️ **版本注入** | 借鉴 K8s 做法,编译期把 git tag/commit 写入二进制并暴露 `/version` 接口 |
| 🐳 **容器化就绪** | 多架构 Dockerfile + docker-compose + K8s Deployment + Jenkinsfile |
| 📦 **离线可构建** | 完整 `vendor/` 目录随仓库提交,内网无代理、无外网也能编译 |
| 🧪 **单元测试** | 缓存、加解密、错误码、国密、随机数等核心模块均有测试用例 |
## ⚡ 60 秒跑起来
**前置条件**:Go 1.27+、一个可连的 MySQL。
```bash
# 1. 克隆
git clone https://github.com/gjing1st/hertz-admin.git
cd hertz-admin
# 2. 改数据库配置(configs/config.yml)
# database.host / username / password / dbname
# 3. 启动
make run
```
服务默认监听 **9680** 端口。数据库和数据表会**自动创建**,并注入一个超级管理员账号:
| 账号 | 密码 |
|---|---|
| `superAdmin12` | `Best@213` |
> ⚠️ 首次登录后请立刻修改默认密码,生产环境请务必替换。
验证服务是否正常:
```bash
curl http://localhost:9680/ha/v1/ping # -> "pong"
curl http://localhost:9680/ha/v1/version # -> 版本信息
```
接口文档(Swagger)已经挂好,浏览器直接打开:
```
http://localhost:9680/swagger/index.html
```
## 📦 离线 / 内网使用(vendor)
仓库已内置完整的 `vendor/` 目录(2004 个文件、约 64 MB),包含全部依赖源码。**无需 GOPROXY、无需 module cache、无需外网即可编译。**
> ⚠️ 提交 vendor 会让仓库体积增大约 64 MB,`git clone` 会相应变慢。这是"离线可构建"的代价,对内网 / 信创环境通常值得。
### 离线构建
`go.mod` 声明的 Go 版本 ≥ 1.14,且仓库中存在 `vendor/modules.txt`,Go 会**自动进入 vendor 模式**,无需额外参数:
```bash
make run # 直接用 vendor 里的源码运行
make build # 产出 ha 二进制
```
想显式指定(或防止将来目录变化导致模式自动切换),手动加上参数:
```bash
go build -mod=vendor -trimpath -o ha ./cmd/ha/main.go
go run -mod=vendor ./cmd/ha/main.go
go test -mod=vendor ./...
```
如果希望彻底锁死 vendor 模式、杜绝意外联网,把参数写进环境变量:
```bash
go env -w GOFLAGS=-mod=vendor
```
### vendor 的维护
`vendor/` 是**生成产物**。改动依赖后必须重新生成并提交:
```bash
go get github.com/xxx/yyy@v1.2.3 # 新增或升级依赖(这一步需要联网)
go mod tidy # 整理 go.mod / go.sum
go mod vendor # 重新生成 vendor/ ← 每次都要执行
go mod verify # 校验依赖完整性
```
三条规则:
1. **`go.sum` 必须提交**,它是 vendor 模式的完整性依据。
2. **不要手工修改 `vendor/` 里的文件**,下次 `go mod vendor` 会被覆盖。
3. **`vendor/modules.txt` 必须与 `go.mod` 保持一致**,否则会报 `inconsistent vendoring`,重跑 `go mod vendor` 即可修复。
### 离线构建镜像
`build/docker/Dockerfile` **已经按 vendor 方式编写**:不设 GOPROXY、不执行 `go mod download`,直接 `go build -mod=vendor` 编译,内网环境同样可以构建:
```bash
make docker
# 或直接
docker build --build-arg LDFLAGS="$(version/version.sh)" -f ./build/docker/Dockerfile -t ha-server:v1.1.0 .
```
```dockerfile
ARG GO_VERSION=1.27.1
ARG ALPINE_VERSION=3.24
FROM golang:${GO_VERSION}-alpine${ALPINE_VERSION} AS build
ARG LDFLAGS
WORKDIR /src
# 依赖已 vendor 进仓库:无需 GOPROXY、无需 go mod download,离线 / 内网环境可直接构建
ENV GOTOOLCHAIN=local
RUN --mount=type=cache,target=/root/.cache/go-build \
--mount=type=bind,target=. \
CGO_ENABLED=0 GOOS=linux go build -mod=vendor -trimpath -ldflags="-s -w ${LDFLAGS}" -o /bin/server ./cmd/ha/main.go
FROM alpine:${ALPINE_VERSION}
COPY --from=build /bin/server /bin/
EXPOSE 9680
ENTRYPOINT [ "/bin/server" ]
```
> ❗ **离线的两个前提**:① 基础镜像 `golang:1.27.1-alpine3.24` 与 `alpine:3.24` 必须先导入本地(`docker save` / `docker load`,或走私有仓库);② `GO_VERSION` 不能低于 `go.mod` 声明的版本。Dockerfile 里已经设了 `ENV GOTOOLCHAIN=local`,版本不匹配时会**直接报错**而不是偷偷联网下载工具链——在无外网环境里,后者只会表现为长时间卡住或超时。
> ❗ **`.dockerignore` 已加入 `!vendor/**` 例外,请勿删除。** 模板自带的 `**/obj` 会连带排除 `vendor/github.com/twitchyliquid64/golang-asm/obj` —— 那是 Go 源码包(69 个 `.go` 文件),不是编译产物。缺了它 `go build -mod=vendor` 会直接失败:
>
> ```
> vendor/github.com/twitchyliquid64/golang-asm/asm/arch/arch.go:9:2:
> cannot find module providing package github.com/twitchyliquid64/golang-asm/obj:
> import lookup disabled by -mod=vendor
> ```
>
> 以后往 `.dockerignore` 里加 `**/bin`、`**/obj` 这类通用排除规则时,记得确认没有误伤 `vendor/`。同时保持 `.gitignore` 中 `vendor/` 仍为注释状态,否则该目录不会被提交。
## 🧭 请求流转
```mermaid
flowchart LR
A[HTTP 请求] --> B[中间件层
recovery · CORS · 访问日志]
B --> C[Router
ha/v1]
C --> D{鉴权}
D -->|公开| E[Controller]
D -->|LoginRequired| E
D -->|AdminRequired| E
D -->|SuperAdminRequired| E
E --> F[Service
业务编排]
F --> G[Store
数据访问]
G --> H[(MySQL)]
G --> I[gcache]
```
## 📁 目录结构
```shell
├── build
│ ├── ci # 持续集成打包脚本
│ └── docker # Dockerfile(支持多架构)
├── cmd
│ └── ha # 主程序入口
├── configs
│ └── config.yml # 应用配置
├── deployments
│ ├── docker-compose # Docker Compose 部署
│ ├── jenkins # Jenkins Pipeline
│ └── k8s # Kubernetes Deployment
├── docs # Swagger 文档(自动生成)
├── internal
│ ├── apiserver # 核心业务(MCSS 分层)
│ │ ├── controller # 控制器:参数校验、响应封装
│ │ ├── router # 路由注册与权限分组
│ │ ├── service # 业务逻辑
│ │ ├── store # 数据访问(database / cache / 初始化数据)
│ │ └── model # entity / dict / request / response
│ └── pkg # 内部公共能力
│ ├── middleware # 鉴权中间件
│ ├── config # 配置加载
│ └── functions # 日志封装
├── pkg
│ ├── errcode # 统一错误码定义
│ ├── global # 全局变量与错误
│ └── utils # 工具集(国密 gm / uuid / slice / map ...)
├── scripts # 环境与构建脚本
├── vendor # 依赖副本(离线构建用,随仓库提交)
├── version # 版本信息(编译期注入)
└── Makefile
```
## 🛡️ 国密支持
`pkg/utils/gm` 提供符合国密标准的算法实现,可直接用于等保、密评场景:
| 算法 | 实现 | 模式 |
|---|---|---|
| SM3 | `gm.Sm3Sum()` / `gm.New()` | 摘要、HMAC |
| SM4 | `gm.NewCipher()` | CBC、ECB、CFB、OFB |
| SM4-GCM | `gm` 包内 GCM 封装 | 认证加密 |
**密码存储方式**:`base64(HMAC-SM3(key=用户名, data=明文密码))`
```go
// 加密
cipher := gm.EncryptPasswd(username, password)
// 校验(常量时间比较,防时序攻击)
ok := gm.CheckPasswd(username, password, cipher)
```
配合用户表上的 `err_num`(错误次数累计)与 `pwd_updated_at`(密码有效期),构成一套完整的登录安全策略。
> 国密算法实现参考自苏州同济金融科技研究院的开源实现(Apache-2.0),版权声明保留在源文件中。
## 🔑 权限模型
三级角色,通过中间件在路由组上声明式注册:
```go
// internal/apiserver/router/v1/auth.go
initSys(r) // 登录即可访问
initAuthAdminRouter(r) // 需管理员权限
initSuperAdminRouter(r) // 需超级管理员权限
```
| 角色 ID | 角色 | 中间件 |
|---|---|---|
| 1 | 超级管理员 | `middleware.SuperAdminRequired()` |
| 2 | 管理员 | `middleware.AdminRequired()` |
| — | 已登录用户 | `middleware.LoginRequired()` |
鉴权走 `Authorization: Bearer `,校验通过后将 `userId` / `username` / `roleId` 注入请求上下文供后续使用。
## 🗄️ 多数据库支持
`internal/apiserver/store/db.go` 已实现七种数据库的适配,覆盖驱动选择、DSN 构造与自动建库:
| 数据库 | `base.dbtype` | 驱动 | 自动建库 |
|---|---|---|---|
| MySQL | `mysql` | `gorm.io/driver/mysql` | ✅ |
| PostgreSQL | `postgresql` | `gorm.io/driver/postgres` | ✅ |
| openGauss | `opengauss` | `gorm.io/driver/postgres`(协议兼容) | ✅ |
| 人大金仓 KingBase | `kingbase` | `gorm.io/driver/postgres`(PG 模式) | ✅ |
| 达梦 DM | `dm` | `github.com/nfjBill/gorm-driver-dm` | — |
| SQLite | `sqlite` | `gorm.io/driver/sqlite` | — |
| ClickHouse | `clickhouse` | `gorm.io/driver/clickhouse` | — |
**默认仅启用 MySQL,其余驱动的 `gorm.Open` 保持注释状态。** 该设计基于两点考虑:其一,多数项目只需一种数据库,全量启用会将未使用的驱动依赖编入二进制;其二,避免未使用驱动的 `init` 函数在进程启动时被触发。
### 切换数据库
| 步骤 | 位置 | 操作 |
|---|---|---|
| 1 | `internal/apiserver/store/db.go` | 注释 MySQL 分支,解除目标数据库分支的注释 |
| 2 | `go.mod` | 引入目标数据库驱动(必须,否则编译失败) |
| 3 | `configs/config.yml` | 将 `base.dbtype` 置为目标数据库标识 |
```yaml
# configs/config.yml
base:
# mysql,postgresql,opengauss,kingbase,clickhouse,sqlite,dm(达梦)
dbtype: postgresql
```
### 方言差异
切换至非 MySQL 数据库时,需确认以下三处:
1. 建表语句中的 MySQL 专有语法,如 `utf8mb4`
2. `gorm:"type:varchar(255)"` 等硬编码字段类型
3. `soft_delete.DeletedAt` 的软删除标记行为
> 上述数据库的适配代码均已随源码提供,欢迎在真实环境验证后提交实测结果。
## 🔢 错误码体系
所有错误统一收敛到 `pkg/errcode`,业务错误码与 HTTP 状态码解耦,前端可据此做精确提示:
```go
// 定义
var (
Success = New(0, "success")
ServerError = New(10000, "服务内部错误")
DBError = New(10001, "数据库操作失败")
...
)
// 使用
c.JSON(http.StatusOK, response.Fail(errcode.DBError))
```
## 🔨 构建与打包
```bash
make help # 查看全部可用命令
make run # 本地运行
make build # 编译二进制(自动注入 git 版本信息)
make docker # 构建镜像并导出 tar.gz
make push_docker # 推送到镜像仓库
make swag # 重新生成 Swagger 文档
```
版本信息由 `version/version.sh` 在编译期通过 `-ldflags` 注入,运行时通过 `GET /ha/v1/version` 查询,包含 `gitVersion`、`gitCommit`、`gitTreeState`、`buildDate`、`goVersion`、`platform`。
## 🚢 部署
### Docker Compose
```bash
cd deployments/docker-compose
docker-compose up -d
```
> `docker-compose.yml` 中默认包含一个前端服务,仅需后端时删除 `frontend` 段即可;同时请确认 `image` 名称与 `make docker` 实际产出的镜像名一致。
### Kubernetes
```bash
kubectl apply -f deployments/k8s/ha-deployment.yaml
```
### 配置说明
`configs/config.yml` 主要配置项:
| 配置项 | 默认值 | 说明 |
|---|---|---|
| `base.port` | `9680` | 服务监听端口 |
| `base.dbtype` | `mysql` | 数据库类型,可选 `mysql` / `postgresql` / `opengauss` / `kingbase` / `dm` / `sqlite` / `clickhouse`(详见「多数据库支持」) |
| `base.cachetype` | `gcache` | 缓存类型(内存缓存) |
| `base.enableIntegrity` | `true` | 是否开启数据完整性校验 |
| `base.pwdMaxErrNum` | `5` | 密码最大错误次数 |
| `log.output` | `std` | 日志输出:`std` / `file` |
| `log.level` | `info` | 日志级别 |
| `database.*` | — | MySQL 连接信息与连接池参数 |
## 🔌 内置接口
| 方法 | 路径 | 说明 | 权限 |
|---|---|---|---|
| GET | `/ha/v1/ping` | 健康检查 | 公开 |
| GET | `/ha/v1/version` | 版本信息 | 公开 |
| GET | `/ha/v1/login-type` | 支持的登录方式 | 公开 |
| GET | `/ha/v1/init/step` | 初始化状态 | 公开 |
| POST | `/ha/v1/user/login` | 登录 | 公开 |
| POST | `/ha/v1/user/register` | 注册 | 公开 |
| POST | `/ha/v1/logout` | 登出 | 公开 |
| GET | `/ha/v1/sys/run` | 系统运行时长 | 已登录 |
| GET | `/ha/v1/sys/status` | 系统运行状态 | 已登录 |
| GET | `/swagger/index.html` | 接口文档 | — |
## 🗺️ Roadmap
- [ ] **多数据库实测反馈**:PostgreSQL / openGauss / 人大金仓 / 达梦 / SQLite / ClickHouse 的适配代码已就绪(默认注释,按需开启),欢迎在真实环境验证后反馈结果,我会补进兼容性说明
- [ ] **CI 流水线**:补充 GitHub Actions(构建、Lint、单元测试)
- [ ] **镜像命名统一**:对齐 `Makefile` 产物名(`ha-server`)与 docker-compose 中的服务镜像名
- [ ] **可选组件**:Casbin 权限模型、Redis 缓存实现、Wire 依赖注入
- [ ] **在线文档站**:基于 GitHub Pages 搭建使用文档
- [ ] **性能基准**:补充框架基准测试并与同类脚手架横向对比
## 🤝 参与贡献
欢迎 Issue 与 PR。
1. Fork 本仓库
2. 新建分支 `git checkout -b feature/your-feature`
3. 提交改动 `git commit -m 'feat: your feature'`
4. 推送分支 `git push origin feature/your-feature`
5. 提交 Pull Request
如果这个项目对你有帮助,欢迎点个 **Star** ⭐ —— 这是我持续维护下去的最大动力。
## 📄 License
[Apache License 2.0](./LICENSE)
---
## 📞 关于我
- 主要从事后端开发,兼具前端、运维及全栈工程师,热爱 `Golang`、`Docker`、`Kubernetes`、`KubeSphere`
- 信创服务器 `K8s` & `KubeSphere` 布道者、`KubeSphere` 离线部署布道者
- 公众号:`编码如写诗`,作者:`天行1st`,微信:`sd_zdhr`
可扫描下方二维码,添加我微信或关注公众号,添加好友请备注 **`ha`**
|
|
| ------------------------------------------------------------ |