1. 授权测试环境快速搭建
1.1 章节概述
搭建一套可复用的授权测试环境是自动化 测试的前提。本章覆盖从零启动的完整流程:用 Docker Compose 编排 MySQL + Redis + 待测应用,配置持久化存储,生成 JWT 签名密钥,并通过 Postman / curl 验证环境健康。
学习目标:10 分钟内完成一套含数据库、缓存、密钥、API 端点可访问的测试沙箱,为后续全场景覆盖测试打好基础。
1.2 架构与组件关系
1.3 核心原理
授权测试环境依赖 隔离性 和 可重复性。采用 Docker Compose 将每个服务组件封装为独立容器:
- MySQL:存储用户凭据、角色、 黑名单;通过初始化脚本预置测试数据。
- Redis:缓存 Refresh 、用户会话,支持高速校验。
- JWT 密钥:使用非对称算法(Ed25519 / RSA256)生成一对公私钥,私钥用于签发,公钥用于验证。
- 待测应用:提供 /auth/, /auth/refresh, /auth/revoke 等端点,通过配置注入数据库和密钥。
1.4 环境搭建步骤
1.4.1 目录结构准备
-test-lab/
├── docker-compose.yml
├── app/
│ ├── Dockerfile
│ └── application.yml
├── db/
│ ├── init.sql
│ └── my.cnf
├── redis/
│ └── redis.conf
└── keys/
└── generate-keypair.sh
1.4.2 Docker Compose 编排文件
version: "3.8"
services:
mysql:
image: mysql:8.0
container_name: auth-mysql
environment:
MYSQL_ROOT_PASSWORD: test123
MYSQL_DATABASE: auth_test
volumes:
- ./db/init.sql:/docker-entrypoint-initdb.d/init.sql
- ./db/my.cnf:/etc/mysql/conf.d/my.cnf
ports:
- "3306:3306"
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 10s
timeout: 5s
retries: 3
redis:
image: redis:7-alpine
container_name: auth-redis
command: redis-server /usr/local/etc/redis/redis.conf --requirepass testpass
volumes:
- ./redis/redis.conf:/usr/local/etc/redis/redis.conf
ports:
- "6379:6379"
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 3
auth-app:
build: ./app
container_name: auth-app
ports:
- "8080:8080"
environment:
DB_HOST: mysql
DB_PORT: 3306
DB_NAME: auth_test
DB_USER: root
DB_PASS: test123
REDIS_HOST: redis
REDIS_PORT: 6379
REDIS_PASS: testpass
JWT_PUBLIC_KEY_PATH: /etc/app/keys/jwt.pub
JWT_PRIVATE_KEY_PATH: /etc/app/keys/jwt.key
volumes:
- ./keys:/etc/app/keys:ro
depends_on:
mysql:
condition: service_healthy
redis:
condition: service_healthy
1.4.3 JWT 密钥生成脚本
#!/bin/bash
# generate-keypair.sh - 生成 Ed25519 密钥对
set -e
KEY_DIR="$(cd "$(dirname "$0")" && pwd)"
PRIVATE_KEY="${KEY_DIR}/jwt.key"
PUBLIC_KEY="${KEY_DIR}/jwt.pub"
if [ -f "$PRIVATE_KEY" ]; then
echo "[SKIP] 密钥已存在"
exit 0
fi
openssl genpkey -algorithm ED25519 -out "$PRIVATE_KEY"
openssl pkey -in "$PRIVATE_KEY" -pubout -out "$PUBLIC_KEY"
chmod 600 "$PRIVATE_KEY"
chmod 644 "$PUBLIC_KEY"
echo "[OK] 密钥生成完毕"
echo " PRIVATE: $PRIVATE_KEY"
echo " PUBLIC: $PUBLIC_KEY"
1.4.4 MySQL 初始化 SQL (init.sql)
CREATE TABLE IF NOT EXISTS users (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL UNIQUE,
password_hash VARCHAR(255) NOT NULL,
role VARCHAR(20) DEFAULT 'user',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
INSERT INTO users (username, password_hash, role) VALUES
('tester', '$2a$10$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy', 'admin'),
('alice', '$2a$10$e0MYzXyjpJS7Pd0RVvHwHeFPL6X5mJ6rE1D1J6dX9yD9X9yD9X9y', 'user')
ON DUPLICATE KEY UPDATE username=username;
CREATE TABLE IF NOT EXISTS _blacklist (
jti VARCHAR(64) PRIMARY KEY,
expired_at DATETIME NOT NULL,
INDEX idx_expired (expired_at)
);
1.5 环境验证(Postman / curl)
| 验证项 | 命令 / 操作 | 期望响应 |
|---|---|---|
| MySQL 连接 | docker exec auth-mysql mysql -u root -ptest123 -e "SELECT 1" | 1 |
| Redis 连接 | docker exec auth-redis redis-cli -a testpass ping | PONG |
| 应用健康检查 | curl -s http://localhost:8080/actuator/health | {"status":"UP"} |
| 获取 (POST) | curl -X POST http://localhost:8080/auth/ -d "grant_type=password&username=tester&password=test123" | JSON 含 access_, refresh_, _type |
| 验证 (GET) | curl -H "Authorization: Bearer <access_>" http://localhost:8080/auth/verify | {"valid":true,"sub":"tester","role":"admin"} |
快速启动:在项目根目录执行
cd -test-lab && bash keys/generate-keypair.sh && docker-compose up -d。等待 20秒后所有容器健康检查通过即可开始测试。
1.6 常见错误与调试
- 容器启动失败:检查端口占用(3306/6379/8080),使用
docker-compose logs mysql查看 MySQL 错误日志。 - JWT 密钥格式错误:确保私钥为 PKCS#8 格式且以
-----BEGIN PRIVATE KEY-----开头。 - 验证返回 403:检查
JWT_PUBLIC_KEY_PATH是否正确映射,应用无法读取挂载的密钥文件。 - 数据库连接拒绝:验证 MySQL 容器健康检查是否通过,
DB_HOST使用服务名mysql而非localhost。
1.7 性能与稳定性优化提醒
测试环境搭建时注意:
- MySQL:生产环境应使用
innodb_buffer_pool_size适当调小(如 256M)避免占用过多内存。 - Redis:设置
maxmemory 128mb和maxmemory-policy allkeys-lru防止测试期间缓存膨胀。 - 应用日志:挂载日志目录
./logs:/app/logs方便定位 JWT 认证异常。 - 密钥轮换:使用
kid(Key ID) 声明在 JWT Header 中,支持多密钥并行验证。