2. Development 环境搭建:本地 Keycloak/Dex 容器部署、HTTPS 自签名证书配置、客户端注册
在 OIDC 异步任务调试中,Development 环境是验证流程正确性的第一道防线。本章将指导你使用 Docker Compose 在本地快速搭建 Keycloak 和 Dex 两套 OIDC 提供者,配置 HTTPS 自签名证书,并完成客户端注册。所有操作均面向异步调试场景,确保后续章节的 Token 颁发、刷新、撤销流程可复现。
2.1 环境概览与组件选择
Development 环境需要模拟生产级 OIDC 流程,但降低复杂度。我们选择两套主流 OIDC 实现:
| 组件 | 角色 | 端口 | 适用场景 |
|---|---|---|---|
| Keycloak | 全功能 OIDC/OAuth2 提供者 | 8443 (HTTPS) | 标准授权码流程、客户端认证、异步 Token 刷新 |
| Dex | 轻量级 OIDC 连接器 | 5556 (HTTPS) | 多后端身份代理、异步 Token 交换、测试环境快速启动 |
| 自签名 CA | 本地信任锚点 | — | 为所有容器签发 TLS 证书,避免浏览器/客户端证书错误 |
异步调试要点: 本地环境使用自签名证书时,异步 HTTP 客户端(如 aiohttp、httpx)需要显式设置
verify=False 或加载 CA 证书。后续章节的异步任务排错将依赖此配置。
2.2 自签名证书体系搭建
使用 OpenSSL 创建本地 CA 并为 Keycloak 和 Dex 签发证书。所有证书存放在 ./certs/ 目录。
# 1. 创建 CA 私钥和自签名根证书
mkdir -p ./certs
openssl genrsa -out ./certs/ca.key 4096
openssl req -x509 -new -nodes -key ./certs/ca.key \
-sha256 -days 3650 \
-subj "/C=CN/ST=Beijing/L=Beijing/O=DevOIDC/CN=DevCA" \
-out ./certs/ca.crt
# 2. 为 Keycloak 生成私钥和 CSR
openssl genrsa -out ./certs/keycloak.key 2048
openssl req -new -key ./certs/keycloak.key \
-subj "/C=CN/ST=Beijing/L=Beijing/O=DevOIDC/CN=keycloak.local" \
-out ./certs/keycloak.csr
# 3. 使用 CA 签发 Keycloak 证书(含 SAN)
cat > ./certs/keycloak.ext <<EOF
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names
[alt_names]
DNS.1 = keycloak.local
DNS.2 = localhost
IP.1 = 127.0.0.1
EOF
openssl x509 -req -in ./certs/keycloak.csr \
-CA ./certs/ca.crt -CAkey ./certs/ca.key \
-CAcreateserial -out ./certs/keycloak.crt \
-days 365 -sha256 -extfile ./certs/keycloak.ext
# 4. 为 Dex 重复相同步骤(CN=dex.local)
openssl genrsa -out ./certs/dex.key 2048
openssl req -new -key ./certs/dex.key \
-subj "/C=CN/ST=Beijing/L=Beijing/O=DevOIDC/CN=dex.local" \
-out ./certs/dex.csr
# 使用类似 keycloak.ext 的 SAN 配置,将 DNS.1 改为 dex.local
openssl x509 -req -in ./certs/dex.csr \
-CA ./certs/ca.crt -CAkey ./certs/ca.key \
-CAcreateserial -out ./certs/dex.crt \
-days 365 -sha256 -extfile ./certs/dex.ext
证书信任: 将
ca.crt 导入操作系统或浏览器的受信任根证书颁发机构。否则异步请求会因 TLS 握手失败而抛出 SSLCertVerificationError,打断调试流程。
2.3 Keycloak 容器部署
使用 Docker Compose 启动 Keycloak,挂载证书并开启 HTTPS。同时配置持久化数据库以保留客户端注册信息。
# docker-compose.yml 片段(Keycloak 部分)
version: '3.8'
services:
keycloak:
image: quay.io/keycloak/keycloak:22.0.5
container_name: oidc-keycloak
command: start --optimized
environment:
KC_HOSTNAME: keycloak.local
KC_HTTPS_CERTIFICATE_FILE: /certs/keycloak.crt
KC_HTTPS_CERTIFICATE_KEY_FILE: /certs/keycloak.key
KC_DB: postgres
KC_DB_URL: jdbc:postgresql://postgres:5432/keycloak
KC_DB_USERNAME: keycloak
KC_DB_PASSWORD: keycloak_pass
KEYCLOAK_ADMIN: admin
KEYCLOAK_ADMIN_PASSWORD: admin
ports:
- "8443:8443"
volumes:
- ./certs:/certs:ro
depends_on:
- postgres
postgres:
image: postgres:15
environment:
POSTGRES_DB: keycloak
POSTGRES_USER: keycloak
POSTGRES_PASSWORD: keycloak_pass
volumes:
- pgdata:/var/lib/postgresql/data
volumes:
pgdata:
启动后访问 https://keycloak.local:8443,使用 admin/admin 登录管理控制台。
2.4 Dex 容器部署
Dex 作为轻量级 OIDC 提供者,配置更简洁。使用静态客户端和本地连接器。
# docker-compose.yml 片段(Dex 部分)
dex:
image: ghcr.io/dexidp/dex:v2.37.0
container_name: oidc-dex
command: dex serve /etc/dex/config.yaml
ports:
- "5556:5556"
volumes:
- ./certs:/certs:ro
- ./dex-config.yaml:/etc/dex/config.yaml:ro
# dex-config.yaml
issuer: https://dex.local:5556
storage:
type: sqlite3
config:
file: /var/dex/dex.db
web:
https: 0.0.0.0:5556
tlsCert: /certs/dex.crt
tlsKey: /certs/dex.key
staticClients:
- id: dev-client
redirectURIs:
- 'https://oidcdebugger.local/callback'
- 'http://localhost:8080/callback'
name: 'Development Client'
secret: dev-secret
connectors:
- type: local
id: local
name: Local Users
config:
users:
- email: test@dev.local
hash: $2a$10$... # bcrypt hash of "password"
异步调试提示: Dex 的 SQLite 存储适合单机开发。若需模拟异步并发场景,可切换至 PostgreSQL 或 etcd 存储后端。
2.5 客户端注册与 OIDC 配置
在 Keycloak 管理控制台中注册一个公开客户端,用于异步授权码流程。
| 参数 | 值 | 说明 |
|---|---|---|
| Client ID | async-debug-client |
唯一标识 |
| Client authentication | Off (公开客户端) | 异步流程中避免客户端密钥泄露 |
| Standard Flow Enabled | ON | 授权码流程 |
| Valid Redirect URIs | https://oidcdebugger.local/callback |
异步回调地址 |
| Web Origins | + |
允许 CORS |
Dex 的客户端已在 staticClients 中定义,无需额外注册。两者均支持以下 OIDC 端点:
- 授权端点:
/auth(Keycloak) //authorize(Dex) - Token 端点:
/token(两者一致) - JWKS 端点:
/certs(Keycloak) //keys(Dex) - UserInfo 端点:
/userinfo(两者一致)
2.6 环境验证与异步测试
使用 curl 验证 Token 端点可达性,并测试异步刷新流程。
# 验证 Keycloak Token 端点(使用客户端凭证模式)
curl -k --cert ./certs/ca.crt \
-X POST "https://keycloak.local:8443/realms/master/protocol/openid-connect/token" \
-d "client_id=async-debug-client" \
-d "grant_type=client_credentials" \
-d "client_secret="
# 验证 Dex Token 端点
curl -k --cert ./certs/ca.crt \
-X POST "https://dex.local:5556/token" \
-d "grant_type=password" \
-d "client_id=dev-client" \
-d "client_secret=dev-secret" \
-d "username=test@dev.local" \
-d "password=password"
异步调试准备: 返回的
access_token 和 refresh_token 将用于后续章节的异步任务调试。建议将 Token 保存为环境变量 OIDC_ACCESS_TOKEN 和 OIDC_REFRESH_TOKEN。
2.7 整体架构图
下图展示了 Development 环境的组件关系与 OIDC 异步流程路径。
2.8 常见问题与排错
| 问题 | 原因 | 解决方案 |
|---|---|---|
| HTTPS 连接被拒绝 | 证书 SAN 不匹配或端口未映射 | 检查 docker-compose ps 确认容器运行;使用 openssl s_client -connect keycloak.local:8443 验证证书 |
| Token 端点返回 401 | 客户端密钥错误或 grant_type 不支持 | 核对 Keycloak 客户端认证方式;Dex 确保 staticClients.secret 匹配 |
| 异步回调收不到授权码 | Redirect URI 未注册或 HTTPS 证书不被信任 | 在客户端配置中添加完整回调地址;将 ca.crt 加入系统信任存储 |
| Dex 启动失败 | 配置文件 YAML 格式错误或 SQLite 权限不足 | 使用 docker logs oidc-dex 查看错误;确保 /var/dex/ 目录可写 |