Keylo 是一个轻量、可扩展的 统一认证与授权服务(Auth Service),为你的多服务系统提供统一的 JWT 签发、Session 管理和 OAuth 支持。
快速上手建议:
- 完整使用步骤见 docs/END_TO_END_QUICKSTART.md
- 完整接口定义见 docs/API_REFERENCE.md
- 多客户端权限建模见 docs/MULTI_CLIENT_RBAC_INTEGRATION.md
- ✅ 基于 RS256 的 JWT 签发与验证,内置 JWKS 公钥发布
- ✅
/v1/auth/token(用户认证)、/v1/admin/token(管理令牌)、/v1/auth/refresh、/v1/auth/logout、/v1/auth/me核心 API(当前 refresh 主要用于管理客户端链路) - ✅ 用户 Token 内省与服务 Token 内省
- ✅ 服务凭证模式与
service_accessToken - ✅ GitHub OAuth 登录,可扩展其他 OAuth 提供商
- ✅ RBAC、管理员客户端、审计日志与黑名单机制
- ✅ PostgreSQL 自动迁移,Redis 可选增强限流、锁定和 OAuth state
- ✅ 使用 Axum 0.8 + Tokio 的模块化 Rust 服务架构
- ✅ Docker / GHCR 镜像发布支持
- ✅ 客户端密钥 bcrypt 哈希存储,杜绝明文泄露风险
- ✅ 生产环境强制 Redis 限流,禁止降级为内存模式
- ✅ 密码复杂度策略(大写、小写、数字、特殊字符)
- ✅ OAuth state 原子消费(GETDEL),消除 TOCTOU 竞态
- ✅ 服务 Token audience 严格校验
- ✅ 数据库连接池大小可通过
DB_POOL_SIZE环境变量配置
- Rust 1.70+ (安装 Rust)
- PostgreSQL 12+ (或使用 Docker)
- Docker & Docker Compose (可选,用于本地开发)
Keylo 包含完整的测试套件,包括单元测试、集成测试、数据库测试和负载测试。
使用提供的测试脚本(推荐):
# Linux/macOS
./scripts/run_tests.sh
# Windows (PowerShell)
./scripts/run_tests.ps1- 启动测试数据库:
docker run -d --name keylo-test-db \
-e POSTGRES_PASSWORD=password \
-e POSTGRES_DB=keylo_test \
-p 5432:5432 postgres:15- 设置环境变量:
export TEST_DATABASE_URL="postgres://postgres:password@localhost:5432/keylo_test"- 运行不同类型的测试:
# 单元测试
cargo test --lib
# 集成测试
cargo test --test integration_test
# 数据库集成测试
cargo test --test database_integration_test
# 负载测试
cargo test --test load_test
# 所有测试
cargo test生成测试覆盖率报告:
cargo install cargo-tarpaulin
cargo tarpaulin --out Html项目包含 GitHub Actions CI/CD 配置,自动运行:
- 代码格式检查 (
cargo fmt) - 代码质量检查 (
cargo clippy) - 安全审计 (
cargo audit) - 完整测试套件
- 覆盖率报告
第三方系统对接 Keylo 的登录流程、Token 内省和服务接入方式见 docs/THIRD_PARTY_INTEGRATION.md。
多客户端统一用户池与 API 级授权接入说明见 docs/MULTI_CLIENT_RBAC_INTEGRATION.md。
完整接口清单见 docs/API_REFERENCE.md。
如果你是以 AgileBoot 这类 Spring Boot 管理后台接入 Keylo,可进一步参考 docs/AGILEBOOT_INTEGRATION.md。
Keylo 的生产部署要求、发布能力边界和密钥轮换建议见以下文档:
git clone https://github.com/bruceblink/Keylo.git
cd keylo复制 .env.example 到 .env:
cp .env.example .env编辑 .env 设置你的配置:
JWT_ISSUER=keylo
JWT_KEY_ID=keylo-rs256-1
# 生产环境建议使用路径方式加载 RSA 密钥
JWT_PRIVATE_KEY_PATH=./keys/private.pem
JWT_PUBLIC_KEY_PATH=./keys/public.pem
DATABASE_URL=postgres://keylo_user:keylo_password@localhost:5432/keylo
SERVER_ADDR=127.0.0.1
SERVER_PORT=2345
ENVIRONMENT=development开发环境下如果未提供 RSA 密钥,Keylo 会使用内置开发密钥对;生产环境必须显式配置私钥和公钥。
docker-compose up -d这将启动:
- PostgreSQL 数据库 (监听
5432) - Redis 服务 (监听
6379, 可选)
等待数据库准备好:
docker-compose pscargo run服务将在 http://127.0.0.1:2345 启动。
查看日志:
RUST_LOG=keylo=debug cargo run为避免 README 与实现长期漂移,完整接口说明统一收敛到专门文档:
- 全量接口与鉴权规则: docs/API_REFERENCE.md
- 多客户端统一用户池与 RBAC: docs/MULTI_CLIENT_RBAC_INTEGRATION.md
- 第三方系统对接: docs/THIRD_PARTY_INTEGRATION.md
- AgileBoot 对接: docs/AGILEBOOT_INTEGRATION.md
- 公开:
POST /v1/auth/token、POST /v1/admin/token、POST /v1/auth/refresh、POST /v1/service/token - 用户:
GET /v1/auth/me、POST /v1/auth/logout、POST /v1/user/change-password - 管理:
/v1/admin/*、/v1/admin/users/*、/v1/admin/services/* - RBAC:
/api/rbac/* - OAuth:公开流程
/v1/auth/oauth/*,管理接口/api/oauth/*
当前实现中:
POST /v1/admin/token返回access_token + refresh_tokenPOST /v1/auth/token当前仅返回access_token
即:POST /v1/auth/refresh 所使用的 refresh_token 主要来源于管理客户端登录链路。
src/
├── main.rs # 启动入口,服务器初始化
├── lib.rs # 库根模块
├── config.rs # 环境配置管理
├── state.rs # AppState 定义,应用全局状态
├── startup.rs # 路由初始化,应用启动逻辑
├── db/ # 数据访问层
├── handlers/ # HTTP handlers
├── middleware/ # 鉴权与授权中间件
├── models/ # 领域模型
├── routes/ # 路由定义(auth/user/rbac/oauth/service)
├── errors.rs # 错误定义
└── utils.rs # 工具函数
docs/ # 对接、发布与运维文档
migrations/ # SQLx 迁移脚本
tests/ # 集成与负载测试
Dockerfile # 容器镜像配置
docker-compose.yml # 开发环境容器编排
Cargo.toml # 项目依赖配置
| 组件 | 技术 | 版本 |
|---|---|---|
| Web 框架 | Axum | 0.8 |
| 异步运行时 | Tokio | 1.0 |
| JWT | jsonwebtoken | 10 |
| 数据库 | SQLx | 0.8 |
| 数据库系统 | PostgreSQL | 12+ |
| 日志 | tracing | 0.1 |
| 序列化 | serde | 1.0 |
| 变量 | 默认值 | 说明 |
|---|---|---|
JWT_ISSUER |
keylo |
JWT 签发方 |
JWT_KEY_ID |
keylo-dev-rs256-1 |
JWKS 中公开的当前密钥 ID |
JWT_PRIVATE_KEY_PATH |
`` | RSA 私钥文件路径,生产推荐 |
JWT_PUBLIC_KEY_PATH |
`` | RSA 公钥文件路径,生产推荐 |
JWT_PRIVATE_KEY_PEM |
`` | RSA 私钥 PEM 内容,可替代路径 |
JWT_PUBLIC_KEY_PEM |
`` | RSA 公钥 PEM 内容,可替代路径 |
DATABASE_URL |
postgres://user:password@localhost:5432/keylo |
数据库连接字符串 |
SERVER_ADDR |
127.0.0.1 |
服务器监听地址 |
SERVER_PORT |
2345 |
服务器监听端口 |
ENVIRONMENT |
development |
运行环境 |
TOKEN_EXPIRY_SECONDS |
900 |
Token 过期时间(秒) |
REFRESH_TOKEN_EXPIRY_SECONDS |
2592000 |
刷新 Token 过期时间(秒) |
MAX_FAILED_LOGIN_ATTEMPTS |
5 |
连续登录失败锁定阈值 |
LOGIN_LOCKOUT_SECONDS |
300 |
登录锁定时长(秒) |
AUTH_RATE_LIMIT_WINDOW_SECONDS |
60 |
登录限流窗口(秒) |
AUTH_RATE_LIMIT_MAX_REQUESTS |
30 |
限流窗口内单主体最大请求数 |
AUTH_GLOBAL_RATE_LIMIT_MAX_REQUESTS |
300 |
限流窗口内全局最大请求数 |
ADMIN_CLIENT_ID |
`` | 管理员客户端 ID(建议生产配置) |
ADMIN_CLIENT_SECRET |
`` | 管理员客户端密钥(建议生产配置) |
REDIS_URL |
`` | Redis 地址(配置后启用分布式状态存储) |
REDIS_KEY_PREFIX |
keylo |
Redis key 前缀(多环境隔离) |
DB_POOL_SIZE |
10 |
数据库连接池最大连接数 |
AUDIT_LOG_RETENTION_DAYS |
30 |
审计日志保留天数 |
SERVICE_TOKEN_EXPIRY_SECONDS |
3600 |
服务 Token 过期时间(秒) |
ENABLE_SUPER_ADMIN_BOOTSTRAP |
false |
是否启用超级管理员首启引导 |
SUPER_ADMIN_USERNAME |
`` | 超级管理员用户名(引导启用时) |
SUPER_ADMIN_EMAIL |
`` | 超级管理员邮箱(引导启用时) |
SUPER_ADMIN_PASSWORD |
`` | 超级管理员初始密码(引导启用时) |
RUST_LOG |
keylo=debug |
日志级别 |
Keylo 默认使用 RS256 签发 JWT,并通过 /.well-known/jwks.json 暴露公开验签密钥集合。
- 生产环境不要使用内置开发密钥
- 下游系统推荐优先使用 JWKS 做本地验签
- 需要统一吊销控制时,继续结合
/v1/auth/introspect和/v1/service/introspect
本地开发如果不显式提供 RSA 密钥,Keylo 会回退到内置开发密钥;生产环境必须显式提供私钥和公钥。
推荐使用 OpenSSL 生成 2048 位或以上的 RSA 密钥对:
mkdir -p keys
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out keys/private.pem
openssl rsa -pubout -in keys/private.pem -out keys/public.pem生成后建议检查文件内容:
openssl pkey -in keys/private.pem -text -noout
openssl pkey -pubin -in keys/public.pem -text -noout如果在 Linux 服务器部署,建议进一步限制私钥权限:
chmod 600 keys/private.pem
chmod 644 keys/public.pem随后配置环境变量:
JWT_KEY_ID=keylo-rs256-1
JWT_PRIVATE_KEY_PATH=./keys/private.pem
JWT_PUBLIC_KEY_PATH=./keys/public.pem如果使用 Docker Compose,默认会把 ${JWT_KEYS_DIR:-./keys} 挂载到容器 /app/keys,因此容器内推荐配置为:
JWT_PRIVATE_KEY_PATH=/app/keys/private.pem
JWT_PUBLIC_KEY_PATH=/app/keys/public.pemKeylo 提供标准探针端点,便于容器编排和网关探活:
GET /healthz:进程存活检查(liveness)GET /readyz:依赖就绪检查(readiness),会返回数据库/Redis 的检查状态
示例:
curl http://127.0.0.1:2345/healthz
curl http://127.0.0.1:2345/readyz服务启动时会自动执行 migrations/ 下的 SQLx 迁移,并初始化默认客户端。当前版本迁移覆盖用户、客户端、刷新 Token、OAuth、RBAC、审计日志和服务客户端等核心表结构。
测试命令与测试脚本请以本文前面的“🧪 测试”章节为准。
docker pull ghcr.io/bruceblink/keylo:v1.1.1docker run --rm -p 2345:2345 \
-v $(pwd)/keys:/app/keys:ro \
-e ENVIRONMENT=production \
-e JWT_ISSUER=keylo \
-e JWT_KEY_ID=keylo-rs256-1 \
-e JWT_PRIVATE_KEY_PATH=/app/keys/private.pem \
-e JWT_PUBLIC_KEY_PATH=/app/keys/public.pem \
-e DATABASE_URL="postgres://keylo_user:keylo_password@db:5432/keylo" \
-e ADMIN_CLIENT_ID="cli-admin-root" \
-e ADMIN_CLIENT_SECRET="replace-with-strong-admin-secret" \
-e REDIS_URL="redis://redis:6379" \
ghcr.io/bruceblink/keylo:v1.1.1docker build -t keylo:latest .docker-compose up -d
docker-compose ps
docker-compose logs -f postgres如果你希望在容器中直接运行 Keylo,请确保同时提供 PostgreSQL、Redis 和 RSA 密钥文件;生产环境不再支持 JWT_SECRET 这种共享密钥模式。
当前仓库的 docker-compose.yml 默认按生产模板组织:
keylo服务默认监听0.0.0.0:2345- compose 与本地统一使用同名变量(如
DATABASE_URL、REDIS_URL),按运行场景调整取值 - 默认要求提供管理客户端(
ADMIN_CLIENT_ID/ADMIN_CLIENT_SECRET) - 默认挂载
${JWT_KEYS_DIR:-./keys}到/app/keys - Redis 默认启用,满足生产环境的限流、登录锁定和 OAuth state 依赖
首次在服务器部署时,建议先准备 .env 或 shell 环境变量,再执行:
docker compose down -v --remove-orphans
docker compose up -d --build
docker compose logs -f keylo-service- 支持用户登录、客户端登录和用户注册
- 支持 Access Token / Refresh Token(当前 refresh 主要用于管理客户端链路)
- 支持
me、登出和黑名单
- 支持服务客户端注册与密钥轮换
- 支持
service_accessToken 签发 - 支持服务 Token 内省与用户 Token 内省
- 默认使用 RS256 与 JWKS
- 下游系统可本地验签
- 高敏接口可叠加内省做实时吊销校验
- 启动时自动执行 SQLx 迁移
- 生产环境强制要求显式 RSA 密钥、管理员客户端和 Redis
- 支持审计日志、限流、登录锁定和 OAuth state 管理
后续增强方向:
- 多把 RSA 密钥并行发布
- 自动密钥轮换流程
- 更细粒度的健康检查与 readiness 探针
- 更完善的网关接入样例
在 src/routes/oauth.rs 和对应 handler 中注册新的 OAuth 提供商逻辑。
编辑 src/models/jwt.rs 中的 Claims 结构与签发逻辑,并同步评估内省与下游验签兼容性。
新增表结构时,优先在 migrations/ 中追加 SQLx 迁移,再更新 src/db/ 下的数据访问层。
- 生产环境:
- 使用 RSA 2048 位或更高密钥
- 私钥只保留在 Keylo 服务端
- 设置
ENVIRONMENT=production - 显式配置
ADMIN_CLIENT_ID、ADMIN_CLIENT_SECRET和REDIS_URL - 为外部访问启用 HTTPS 和反向代理
- 下游系统:
- 优先通过 JWKS 获取公钥并做本地验签
- 在
kid不匹配或验签失败时刷新 JWKS 缓存 - 对强实时吊销场景补充调用内省接口
- 数据库与运行环境:
- 使用强数据库密码并限制网络暴露
- 定期备份 PostgreSQL 数据
- 不要在生产环境启用开发密钥或数据库失败回退模式
欢迎提交 Issue 和 Pull Request,详细开发约定见 CONTRIBUTING.md。
MIT License - 查看 LICENSE 文件
- 📧 提交 Issue: GitHub Issues
- 💡 讨论: GitHub Discussions
Last Updated: 2026年04月17日