feat(auth): 实现统一认证模块及登录策略

- 新增 ApiResult 统一响应封装类,规范前端接口返回结构
- 添加 AuthController,支持多种登录方式及用户信息接口
- 实现 AuthService,包含登录、登出、密码修改、绑定手机号、重置密码等功能
- 集成图形验证码校验和登录失败锁定机制,增强安全性
- 支持邮箱登录和手机号验证码登录,完善多样化认证策略
- 实现 JWT 令牌签发与吊销,确保会话安全管理
- 配置不同环境 application.yml 及配置,支持多租户和灵活缓存配置
- 增加 .gitignore 规则,屏蔽构建产物、IDE 文件和敏感配置
- 引入 AuthProperties 以配置登录与验证码策略参数
This commit is contained in:
2026-09-23 11:59:45 +08:00
parent 87f36825f8
commit 5e86ebe6b7
134 changed files with 8747 additions and 0 deletions
+145
View File
@@ -0,0 +1,145 @@
# 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` |