IAM Service
身份与访问管理服务(Identity and Access Management)。
版本:v0.2.0(对齐 coord-final-decisions I1-I8 + president §2.15/§2.16/§3.2/§5.5) 详细设计见 02-architecture-design.md
职责
- 用户注册 / 登录 / 刷新令牌 / 登出
- JWT RS256 签发(access 15min + refresh 7day,jti 黑名单)
- 角色(Role)与权限(Permission)管理(三层角色模型:system/organization/temporary)
- DataScope 6 级数据范围(self/subject/class/grade/school/all)
- 视口(Viewport)配置查询
- 学生-家长关系管理(
GetChildrenByParent) - 审计日志(
iam_user_audit_log+AuditCreated事件) - JWKS 公钥暴露(供 api-gateway 验签)
- 双入口:REST
/v1/iam/*+ gRPC 50052(packagenext_edu_cloud.iam.v1,12 RPC)
技术栈
- NestJS 10 + TypeScript(ESM,NodeNext)
- Drizzle ORM + MySQL(10 张表)
- bcrypt 密码哈希(cost ≥ 12)
- jsonwebtoken RS256(本地文件密钥)
- ioredis(权限缓存 TTL 5min + token jti 黑名单)
- kafkajs + shared-ts OutboxModule(事务性事件发布)
- @nestjs/microservices + @grpc/grpc-js(gRPC server)
- pino 日志 / prom-client 指标 / OpenTelemetry 链路
端口
| 服务 | 端口 | 备注 |
|---|---|---|
| iam HTTP | 3002 | REST 入口(PORT) |
| iam gRPC | 50052 | gRPC 入口(GRPC_PORT) |
环境变量
| 变量 | 说明 | 默认值 |
|---|---|---|
PORT |
HTTP 端口 | 3002 |
GRPC_PORT |
gRPC 端口 | 50052 |
DATABASE_URL |
MySQL 连接串 | — |
REDIS_URL |
Redis 连接串 | — |
IAM_PRIVATE_KEY_PATH |
RS256 私钥文件路径 | — |
IAM_PUBLIC_KEY_PATH |
RS256 公钥文件路径 | — |
JWT_ISSUER |
JWT 签发者 | next-edu-cloud |
JWT_AUDIENCE |
JWT 受众 | next-edu-cloud |
JWT_KEY_ID |
密钥 ID(kid,用于 JWKS 轮换) | iam-rs256-v1 |
ACCESS_TOKEN_TTL |
access_token TTL | 15m |
REFRESH_TOKEN_TTL_DAYS |
refresh_token TTL(天) | 7 |
KAFKA_BROKERS |
Kafka broker 列表(逗号分隔) | — |
KAFKA_CLIENT_ID |
Kafka client ID | iam-service |
OTEL_EXPORTER_OTLP_ENDPOINT |
OTel OTLP 端点(可选) | — |
LOG_LEVEL |
日志级别 | info |
NODE_ENV |
环境标识 | development |
REST API
| Method | Path | 权限 | 说明 |
|---|---|---|---|
| POST | /v1/iam/register |
公开 | 注册 |
| POST | /v1/iam/login |
公开 | 登录 |
| POST | /v1/iam/refresh |
公开 | 刷新令牌(轮换 + 旧 jti 加黑名单) |
| POST | /v1/iam/logout |
IAM_USER_READ |
登出 |
| GET | /v1/iam/me |
IAM_USER_READ |
当前用户信息 |
| GET | /v1/iam/viewports |
IAM_USER_READ |
当前用户视口 |
| GET | /v1/iam/permissions/effective |
IAM_USER_READ |
当前用户有效权限 |
| GET | /v1/iam/children |
IAM_USER_READ |
家长的孩子列表 |
| GET | /v1/iam/roles |
IAM_ROLE_MANAGE |
角色列表 |
| GET | /v1/iam/permissions |
IAM_ROLE_MANAGE |
权限点列表 |
| GET | /v1/iam/audit |
IAM_AUDIT_READ |
审计日志 |
| GET | /v1/iam/.well-known/jwks.json |
公开 | RS256 公钥 JWK Set |
gRPC API
12 RPC,proto 定义见 packages/shared-proto/proto/iam.proto,package next_edu_cloud.iam.v1:
Register / Login / RefreshToken / Logout / GetUserInfo / BatchGetUsers / GetEffectivePermissions / GetEffectiveAccess / GetEffectiveDataScope / GetViewports / GetPublicKey / GetChildrenByParent
健康检查
| 端点 | 用途 | 鉴权 |
|---|---|---|
GET /healthz |
存活探针(liveness),仅返回进程状态 | 无 |
GET /readyz |
就绪探针(readiness),检查 DB/Redis/Kafka/JWKS/gRPC 5 依赖,失败返回 503 | 无 |
数据表(10 张)
| 表名 | 用途 |
|---|---|
iam_users |
用户主表 |
iam_roles |
角色表(role_type + level) |
iam_user_roles |
用户-角色绑定 |
iam_permissions |
权限点表 |
iam_role_permissions |
角色-权限映射 |
iam_refresh_tokens |
refresh token(含 jti) |
iam_role_viewports |
角色-视口配置(含 level) |
iam_student_guardians |
学生-家长关系 |
iam_user_audit_log |
审计日志 |
iam_password_history |
密码重用限制 |
DDL + 种子数据见 scripts/iam-init.sql。
Kafka 事件
| Topic | 事件 |
|---|---|
edu.iam.user.events |
UserCreated |
edu.iam.role.events |
RoleChanged |
edu.iam.audit.created |
AuditCreated |
通过 shared-ts OutboxModule 事务性发布(at-least-once + idempotent producer)。
开发
# 安装依赖
pnpm install
# 初始化数据库(需先启动 MySQL + Redis + Kafka)
mysql -u root -p < scripts/iam-init.sql
# 生成 RS256 密钥对
openssl genrsa -out private.pem 2048
openssl rsa -in private.pem -pubout -out public.pem
# 启动开发服务
pnpm --filter @edu/iam-service dev
# 质量校验
pnpm --filter @edu/iam-service lint
pnpm --filter @edu/iam-service typecheck