# iam-api 开发计划 > 统一身份中心(Identity & Access Management)。目标:把「用户 / 租户 / 角色 / 权限 / > 菜单 / 登录 / 令牌签发」从 `open-api` 里抽出来,成为 `open-api` 与 `dp-api` 共用的 > 唯一账号源,使 `dp-api` 可以脱离 `open-api` 独立售卖与部署。 ## 1. 定位与边界 ### 1.1 iam-api 负责 | 能力 | 说明 | |---|---| | 身份(Identity) | 租户、用户、账号密码 / 邮箱 / 手机号、密码强度与找回、绑定手机 | | 授权(Access) | 角色、权限标识、菜单(菜单即权限载体)、用户-角色-菜单关系 | | 会话(Session) | 控制台登录态令牌(HS256)、登出吊销、登录失败锁定、登录审计 | | 令牌(Token) | 面向资源服务的 RS256 access token、refresh token、JWKS、introspect、revoke | | 客户端(Client) | `iam_client` 注册表:登记 open-api / dp-api 等消费方及其允许的 scope / aud | ### 1.2 iam-api 不负责 - 开放平台的业务语义:应用管理、OAuth2 授权页、scope 字典、令牌签发统计(留在 `open-api`)。 - 数据中台的业务数据:服务器、客户、订单、合同、发票、支付(留在 `dp-api`)。 - 通用底座:云存储、系统设置、字典、附件、消息、审计(后续放 `base-api`)。 > 边界一句话:**iam-api 只知道“你是谁、你能干什么”,不知道“你干的是什么业务”。** ### 1.3 与 open-api / dp-api 的关系 ``` ┌──────────────────────────────┐ │ iam-api │ │ 账号/租户/角色/权限/菜单/令牌 │ └───────────┬──────────────────┘ RS256 令牌 + JWKS │ RS256 令牌 + JWKS ┌─────────────────────┴─────────────────────┐ ▼ ▼ ┌─────────────┐ ┌─────────────┐ │ open-api │ │ dp-api │ │ 开放平台 │ │ 数据中台 │ └─────────────┘ └─────────────┘ ``` - 两个资源服务都只通过 JWKS 验签,不共享用户表、不共享对称密钥。 - 同一个 `user_id` 可以在两个产品里拥有不同角色: `iam_user_role` 带 `client_id`(为空表示控制台全局角色),授权按消费者隔离。 ## 2. 里程碑 ### M1 内核与骨架(本期) - [x] Maven 工程、Spring Boot 3.5 / Java 25、Flyway、MyBatis-Plus - [x] 统一返回结构、全局异常、分页与查询参数封装 - [x] 多租户上下文与 MyBatis-Plus 租户插件 - [x] 缓存抽象 `CacheStore`(Redis / 内存双实现,演示与测试免 Redis) ### M2 身份与授权(本期) - [x] `sys_tenant` / `sys_user` / `sys_role` / `sys_menu` / 关联表 / 登录审计 - [x] 租户、用户、角色、菜单的查询与管理接口 - [x] 用户带角色与权限集合,供控制台做按钮级权限 ### M3 登录与安全(本期) - [x] 账号密码登录(图形验证码 + 失败锁定) - [x] 邮箱登录、手机号验证码登录 - [x] 登出(令牌吊销)、`/api/me`、修改密码、绑定/换绑手机号、自助找回密码 - [x] HS256 会话令牌 + 认证过滤器 + 401/403 统一处理 ### M4 统一令牌与客户端(本期) - [x] `iam_client` 客户端注册表与 scope 白名单 - [x] RS256 令牌签发:`client_credentials` / `authorization_code(PKCE)` / `refresh_token` - [x] `/api/v1/oauth/jwks` 公钥集合、`/api/v1/oauth/introspect`、`/api/v1/oauth/revoke` - [x] 授权码存储与一次性核销(`iam_auth_code`) ### M5 迁出与联调(下一期) - [ ] open-api 改为 iam-api 的客户端:登录跳转/代理、用户信息改读 iam-api - [ ] dp-api 接入:JWKS 验签 + `tenant_id` / 角色映射 - [ ] 存量用户迁移脚本(`db_open.sys_user` → `iam_user`)与双写过渡 - [ ] 平台运营端(账号开通、跨租户管理)迁到 iam-api 或独立的 iam-admin ### M6 单点登录与合规(远期) - [ ] SSO 会话表 `iam_sso_session` 与跨域免登票据 - [ ] MFA(TOTP)、登录设备管理、异常登录提醒 - [ ] 审计中心:把登录审计升级为操作审计 ## 3. 数据模型 | 表 | 说明 | |---|---| | `sys_tenant` | 租户 | | `sys_user` | 用户(BCrypt 密码,邮箱/手机号可空) | | `sys_role` | 角色 | | `sys_user_role` | 用户-角色 | | `sys_menu` | 菜单 / 权限点 | | `sys_role_menu` | 角色-菜单 | | `sys_login_record` | 登录审计 | | `iam_client` | 接入方(client_id / secret / 允许 scope / 令牌有效期) | | `iam_auth_code` | OAuth2 授权码(一次性、短有效期) | 所有业务表统一:`del_flag` 逻辑删除、`create_time` / `update_time` 应用层填充。 ## 4. 接口一览(本期) | 分组 | 接口 | |---|---| | 认证 | `POST /api/login`、`POST /api/loginByEmail`、`POST /api/loginBySms`、`POST /api/logout`、`GET /api/me`、`POST /api/changePassword`、`POST /api/resetPassword`、`POST /api/bindPhone`、`POST /api/bindPhone/captcha` | | 验证码 | `GET /api/captcha`、`POST /api/sendSmsCaptcha`、`POST /api/sendEmailCaptcha` | | 租户 | `GET/POST/PUT/DELETE /api/iam/tenant`、`GET /api/iam/tenant/{id}` | | 用户 | `GET /api/iam/user`、`POST /api/iam/user`、`PUT /api/iam/user/{id}`、`DELETE /api/iam/user/{id}`、`POST /api/iam/user/{id}/resetPassword` | | 角色 | `GET /api/iam/role`、`POST /api/iam/role`、`PUT /api/iam/role/{id}`、`DELETE /api/iam/role/{id}`、`PUT /api/iam/role/{id}/menus` | | 菜单 | `GET /api/iam/menu/tree`、`POST /api/iam/menu`、`PUT /api/iam/menu/{id}`、`DELETE /api/iam/menu/{id}` | | 客户端 | `GET /api/iam/client`、`POST /api/iam/client`、`PUT /api/iam/client/{id}`、`DELETE /api/iam/client/{id}`、`POST /api/iam/client/{id}/secret` | | 令牌 | `POST /api/v1/oauth/token`、`GET /api/v1/oauth/jwks`、`POST /api/v1/oauth/introspect`、`POST /api/v1/oauth/revoke` | ## 5. 配置 | 配置项 | 说明 | 默认 | |---|---|---| | `server.port` | 服务端口 | `8900` | | `iam.cache.type` | 缓存实现:`redis` / `memory` | `redis`(`demo`/`test` 为 `memory`) | | `config.jwt.secret` | 控制台会话令牌密钥(HS256) | 开发默认值,生产必须覆盖 | | `config.iam-jwt.private-key` | 资源服务令牌私钥(RS256,PEM) | 缺省时启动生成临时密钥并告警 | | `config.internal-key` | introspect 调用方自证密钥 | `change-me` | ## 6. 部署 - 端口 `8900`,与 `open-api`(8800) / `dp-api`(18800) 并存。 - 生产用 Docker(`Dockerfile` + `docker-compose.yml`),MySQL + Redis 由编排提供。 - 演示与测试走 `-Pdemo` / `test` profile,H2 + 内存缓存,无外部依赖。 - Flyway 用**独立迁移账号**(`FLYWAY_USER` / `FLYWAY_PASSWORD`),与业务账号分离: Flyway 建连接时要读 `performance_schema.user_variables_by_thread`,业务账号不该为此扩权。 建号脚本 `scripts/create-flyway-user.sql`;无法授权时用 `scripts/apply-migrations.sh` 手工迁移。 ## 7. 风险与对策 | 风险 | 对策 | |---|---| | 双用户表导致身份漂移 | 迁移期以 iam-api 为准,open-api / dp-api 只读;禁止双向写 | | 令牌吊销的传播延迟 | access token 短有效期(默认 2h)+ 资源服务就近校验 + introspect 兜底 | | Redis 不可用导致全员无法登录 | `CacheStore` 降级策略与 `iam.cache.type` 显式切换,健康检查暴露状态 | | 认证与业务耦合 | 资源服务只依赖 JWKS 公钥,不引入 iam-api 的代码依赖 | | 迁移账号权限不足导致启动失败 | Flyway 独立账号 + 建号脚本;退路是关闭 Flyway 用 `scripts/apply-migrations.sh` |