1. 授权测试环境快速搭建

1.1 章节概述

搭建一套可复用的授权测试环境是自动化 测试的前提。本章覆盖从零启动的完整流程:用 Docker Compose 编排 MySQL + Redis + 待测应用,配置持久化存储,生成 JWT 签名密钥,并通过 Postman / curl 验证环境健康。

学习目标:10 分钟内完成一套含数据库、缓存、密钥、API 端点可访问的测试沙箱,为后续全场景覆盖测试打好基础。

1.2 架构与组件关系

授权测试环境组件关系图 Postman / curl 待测应用 (Spring Boot) MySQL 8.0 Redis 7.x 密钥生成脚本(openssl/ed25519) 密钥文件挂载到容器 /etc/app/keys/jwt.key

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 pingPONG
应用健康检查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 中,支持多密钥并行验证。