一个轻量级的 API 密钥鉴权管理服务,基于 Go + SQLite 构建,内置 Web 管理界面,开箱即用。
- 管理员登录 — 用户名/密码登录,颁发 JWT(有效期 24 小时)
- API 密钥管理 — 创建、列出、查询、删除密钥
- 密钥有效期 — 支持设置到期时间,或永久有效
- 密钥验证 — 提供公开端点供业务系统校验密钥合法性
- Web 管理界面 — 内嵌单页应用,开箱即用,无需额外部署前端
- SQLite 持久化 — 零外部依赖,数据存储在本地文件
- Docker 支持 — 多阶段构建,提供 docker compose 一键部署
AuthServer/
├── main.go # 服务入口,路由注册
├── go.mod / go.sum
├── Dockerfile
├── docker-compose.yml
├── .env.example # 环境变量配置示例
├── web/
│ └── index.html # 内嵌 Web 管理界面
└── internal/
├── config/config.go # 配置加载(环境变量)
├── models/
│ ├── admin.go # Admin 数据模型
│ └── apikey.go # APIKey 数据模型及请求结构
├── database/database.go # SQLite 连接与 Schema 迁移
├── repository/
│ ├── admin_repo.go # 管理员数据访问层
│ └── key_repo.go # 密钥数据访问层
├── handlers/
│ ├── auth.go # 登录 Handler
│ └── keys.go # 密钥 CRUD Handler
└── middleware/
└── jwt.go # JWT 鉴权中间件
# 1. 复制并编辑环境变量
cp .env.example .env
# 2. 构建镜像(目标平台 linux/amd64)
docker compose build
# 3. 启动服务
docker compose up -d
# 4. 查看运行日志
docker compose logs -f服务启动后访问:http://<your-host>:8080/
需要 Go 1.21+,且系统安装了 gcc(go-sqlite3 依赖 CGO)
CGO_ENABLED=1 go run .所有配置均通过环境变量注入,未设置时使用括号内的默认值。
| 变量名 | 默认值 | 说明 |
|---|---|---|
JWT_SECRET |
change-me-in-production-secret-key-32chars |
JWT 签名密钥,生产环境必须修改 |
ADMIN_USER |
admin |
初始管理员用户名(仅首次启动时写入数据库) |
ADMIN_PASS |
admin123 |
初始管理员密码,生产环境必须修改 |
DB_PATH |
./authserver.db |
SQLite 数据库文件路径 |
SERVER_ADDR |
:8080 |
监听地址,格式为 [host]:port |
HOST_PORT |
8080 |
(仅 docker compose)宿主机映射端口 |
注意:
ADMIN_USER/ADMIN_PASS只在数据库中不存在任何管理员时生效,用于初始化。修改后重启服务不会覆盖已有账户。
JWT_SECRET=your-very-long-random-secret-key-here
ADMIN_USER=admin
ADMIN_PASS=your-strong-password
HOST_PORT=8080受保护的端点需要在请求头中携带登录后获得的 JWT:
Authorization: Bearer <token>
POST /admin/login — 无需认证
请求体
{
"username": "admin",
"password": "admin123"
}成功响应 200
{
"token": "eyJhbGci...",
"username": "admin",
"expires_in": 86400
}失败响应 401
{ "error": "invalid credentials" }POST /api/keys — 需要 JWT
请求体
{
"description": "Mobile App · Production",
"expires_in": 720
}| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
description |
string | ✅ | 密钥用途描述 |
expires_in |
int | ❌ | 有效期(小时),不传或传 0 表示永不过期 |
成功响应 201
{
"id": 1,
"key_value": "a3f8c1d2e4b5...",
"description": "Mobile App · Production",
"expires_at": "2026-05-22T09:00:00Z",
"created_at": "2026-04-21T09:00:00Z",
"is_active": true
}GET /api/keys — 需要 JWT
成功响应 200
{
"total": 2,
"keys": [
{
"id": 1,
"key_value": "a3f8c1d2...",
"description": "Mobile App",
"expires_at": "2026-05-22T09:00:00Z",
"created_at": "2026-04-21T09:00:00Z",
"is_active": true,
"expired": false
},
{
"id": 2,
"key_value": "9e7b4a1f...",
"description": "Legacy Key",
"expires_at": "2025-01-01T00:00:00Z",
"created_at": "2025-01-01T00:00:00Z",
"is_active": true,
"expired": true
}
]
}响应中
expired字段为服务端实时计算,表示密钥是否已超过有效期。
GET /api/keys/:id — 需要 JWT
成功响应 200 — 返回单个密钥对象(格式同上)
失败响应 404
{ "error": "key not found" }PUT /api/keys/:id/expiry — 需要 JWT
请求体
{ "expires_in": 48 }expires_in 值 |
效果 |
|---|---|
正整数(如 48) |
从当前时间起 N 小时后过期 |
0 |
设为永不过期(清除过期时间) |
成功响应 200 — 返回更新后的密钥对象
DELETE /api/keys/:id — 需要 JWT
成功响应 200
{ "message": "key deleted" }失败响应 404
{ "error": "key not found" }POST /api/keys/verify — 无需 JWT,供业务系统调用
请求体
{ "key": "a3f8c1d2e4b5..." }验证通过 200
{
"valid": true,
"key_id": 1,
"description": "Mobile App · Production"
}验证失败 401
{ "valid": false, "error": "key not found" }
{ "valid": false, "error": "key is inactive" }
{ "valid": false, "error": "key expired at 2026-01-01T00:00:00Z" }GET /health — 无需认证
{ "status": "ok" }访问 http://<host>:8080/ 打开内置管理界面。
- 登录页 — 输入管理员用户名和密码,获取 JWT(自动存储于
localStorage) - 仪表盘 — 展示密钥统计(总数 / 有效 / 已过期)
- 创建密钥 — 填写描述和可选有效期,自动生成 64 位随机十六进制密钥
- 密钥列表 — 状态徽章标注有效/已过期/永久,支持一键复制密钥值
- 改期 — 弹窗修改有效期,
0表示永不过期 - 删除 — 二次确认后删除
服务启动时自动执行 Schema 迁移,无需手动建表。
admins 表
| 字段 | 类型 | 说明 |
|---|---|---|
id |
INTEGER PK | 自增主键 |
username |
TEXT UNIQUE | 用户名 |
password_hash |
TEXT | bcrypt 哈希值 |
created_at |
DATETIME | 创建时间 |
api_keys 表
| 字段 | 类型 | 说明 |
|---|---|---|
id |
INTEGER PK | 自增主键 |
key_value |
TEXT UNIQUE | 64 位随机十六进制密钥 |
description |
TEXT | 描述 |
expires_at |
DATETIME | 过期时间,NULL 表示永不过期 |
created_at |
DATETIME | 创建时间 |
is_active |
INTEGER | 是否有效(1/0) |
-
修改默认密钥和密码,在
.env中设置强随机值:# 生成随机 JWT_SECRET openssl rand -hex 32 -
数据备份:定期备份
/data/authserver.db(docker volume 路径) -
反向代理:建议在 Nginx / Caddy 前置,启用 HTTPS
-
端口隔离:生产环境将
HOST_PORT绑定到127.0.0.1,通过反向代理对外暴露
| 组件 | 版本 |
|---|---|
| Go | 1.21 |
| gin-gonic/gin | v1.9.1 |
| mattn/go-sqlite3 | v1.14.22 |
| golang-jwt/jwt | v5.2.1 |
| golang.org/x/crypto | v0.21.0 |