Files
loan-pricing/docs/superpowers/specs/2026-03-30-login-password-encryption-design.md

266 lines
8.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 系统登录与密码类接口加密传输设计文档
## 1. 背景
当前系统登录、注册、修改密码、重置密码、新增用户等正式接口,在请求体中直接传输明文密码。后端在收到密码后再执行现有的登录校验或 BCrypt 加密入库逻辑。
本次需求是在不改变现有业务语义的前提下,为所有正式密码提交接口增加“密码加密传输”能力,避免密码以明文形式直接出现在接口请求体中。
## 2. 已确认约束
- 采用对称加密方案
- 前端使用固定密钥加密密码字段
- 后端使用同一固定密钥解密密码字段
- 覆盖所有正式密码提交接口
- 明确不包含 `/login/test`
- 不新增兼容性或补丁性方案
- 不允许“解密失败后按明文继续处理”
- 保持最短路径实现,不改现有账号、认证、密码存储主逻辑
## 3. 接口范围
本次加密传输仅覆盖以下正式接口:
- `/login`
- `/register`
- `/system/user/profile/updatePwd`
- `/system/user/resetPwd`
- `/system/user`
各接口需要处理的密码字段如下:
- `/login``password`
- `/register``password`
- `/system/user/profile/updatePwd``oldPassword``newPassword`
- `/system/user/resetPwd``password`
- `/system/user``password`
以下接口不在本次范围内:
- `/login/test`
- 任何不提交密码字段的接口
## 4. 现状分析
### 4.1 前端现状
当前前端接口调用中,登录、注册、个人修改密码、管理员重置密码、管理员新增用户都直接提交明文密码字段。仓库中虽然已经存在 `JSEncrypt` 工具,但仅用于“记住密码”场景下 Cookie 的本地存储加密,并没有用于登录或其他正式密码接口。
### 4.2 后端现状
后端正式接口的密码处理链路如下:
- 登录接口直接读取 `LoginBody.password` 并交给认证流程
- 注册接口直接读取 `RegisterBody.password` 并执行 BCrypt 加密入库
- 修改密码接口直接读取 `oldPassword``newPassword` 并执行旧密码校验和新密码入库
- 管理员重置密码和新增用户接口直接读取 `SysUser.password` 并执行 BCrypt 加密
现有后端没有统一的密码传输解密层,因此如果直接在前端加密而后端不解密,现有校验链路会全部失效。
## 5. 方案对比
### 方案一:保留现有字段名,前端加密后提交,后端统一解密
做法:
- 保持现有请求结构不变
- 前端在 API 提交前仅加密密码字段
- 后端在控制器进入业务逻辑前,对密码字段统一解密
优点:
- 改动路径最短
- 页面、DTO、控制器入参结构基本不变
- 现有业务校验和 BCrypt 逻辑可直接复用
缺点:
- 需要明确每个接口的密码字段清单
- 前后端都要维护一份受控字段映射
### 方案二:新增专用密文字段
做法:
- 每个接口新增 `encryptedPassword``encryptedOldPassword` 等字段
- 后端只处理密文字段
优点:
- 语义清楚
- 明文和密文边界直观
缺点:
- 改动面大
- 前后端 DTO、表单、测试样例都要整体调整
- 不符合本次最短路径实现原则
### 方案三:全局请求拦截器加密 + 全局参数层解密
做法:
- 前端在 axios 拦截器中按 URL 自动加密密码字段
- 后端在过滤器或参数解析层统一自动解密
优点:
- 页面层改动最少
缺点:
- 隐式逻辑过重
- 对不同入参类型的接口可读性差
- 不利于后续定位问题
## 6. 设计结论
采用方案一。
本次仅在接口边界增加密码加密传输能力,业务层继续只处理解密后的明文密码。传输链路如下:
1. 前端表单收集用户输入的密码明文
2. API 提交前,使用固定对称密钥加密密码字段
3. 后端控制器收到请求后,先对约定密码字段解密
4. 解密成功后继续走现有业务逻辑
5. 解密失败时直接返回错误,不进入后续业务处理
`/login/test` 保持现状,不加入加密与解密逻辑。
## 7. 前端设计
### 7.1 设计目标
前端只负责“在请求发出前对密码字段加密”,不在页面组件中分散实现逻辑,也不修改表单字段命名。
### 7.2 收口位置
加密逻辑收口在 API 调用层,不放在页面组件层。
原因:
- 登录页、注册页、个人中心、用户管理都存在密码提交场景
- 若每个页面独立处理,加密逻辑容易分散和重复
- API 层更容易统一维护接口与字段映射
### 7.3 前端改动点
- 新增统一的对称加密工具
- 新增“密码字段加密”辅助方法
- 在以下接口调用前对对应字段加密:
- 登录
- 注册
- 个人修改密码
- 管理员重置密码
- 管理员新增用户
- 保持请求字段名不变
### 7.4 配置方式
前端固定密钥通过环境配置读取,不直接散落在业务代码中。
## 8. 后端设计
### 8.1 设计目标
后端只负责“在进入现有业务逻辑前将密码字段解密为明文”,不改动现有认证和密码存储主流程。
### 8.2 收口位置
解密逻辑收口在控制器入口之后、业务逻辑之前,由统一的密码解密工具完成。
原因:
- 当前接口入参类型不统一,包含 `LoginBody``RegisterBody``SysUser``Map<String, String>`
- 如果直接放到全局过滤器或参数解析层,会增加隐式复杂度
- 控制器显式调用统一解密工具,路径更短、更直观
### 8.3 后端改动点
- 新增统一的对称解密工具
- 新增面向不同入参类型的密码字段解密方法
- 在以下正式接口进入业务逻辑前显式解密:
- `SysLoginController.login`
- `SysRegisterController.register`
- `SysProfileController.updatePwd`
- `SysUserController.resetPwd`
- `SysUserController.add`
- 不改动 `SysLoginController.loginWithoutCaptcha`
### 8.4 业务链路保持不变
解密成功后继续沿用现有逻辑:
- 登录继续走认证管理器与 `SysPasswordService`
- 注册继续走 BCrypt 加密入库
- 个人修改密码继续先校验旧密码,再加密新密码入库
- 管理员重置密码和新增用户继续走 BCrypt 加密入库
## 9. 配置设计
前后端分别维护固定对称密钥配置:
- 前端从环境变量读取固定密钥
- 后端从 `application.yml` 读取固定密钥
本次设计默认前后端使用同一把固定密钥,不涉及动态下发、轮换或多套密钥管理。
## 10. 错误处理
本次只采用单一路径,不做兼容分支:
- 受控正式接口收到密码字段后,后端默认按密文处理
- 任一密码字段解密失败,接口直接返回错误
- 不允许“尝试解密失败后继续按明文处理”
- 不允许只加密部分密码字段后继续流转
修改密码接口中,`oldPassword``newPassword` 必须同时成功解密后才能进入现有校验流程。
## 11. 非目标
本次不包含以下内容:
- 不修改 `/login/test`
- 不改造密码存储方式
- 不改造现有 BCrypt 校验逻辑
- 不引入非对称加密
- 不增加密钥动态下发能力
- 不增加明密文双通道兼容逻辑
- 不修改与密码无关的请求字段
## 12. 风险与控制
主要风险如下:
1. 前后端固定密钥不一致,会导致所有正式密码接口失败
2. 某些密码字段漏加密或漏解密,会导致登录失败或入库异常
3. 个人修改密码接口包含多个密码字段,若字段映射错误,会导致旧密码校验失败
控制方式:
- 前后端统一约定固定密钥配置名称与用途
- 将密码字段清单明确写入实现计划
- 将正式接口逐一纳入测试验证
- 保持 `/login/test` 完全不接入,避免影响现有测试用途
## 13. 验证方案
实施后至少验证以下场景:
1. `/login` 提交加密后的 `password` 可以正常登录
2. `/register` 提交加密后的 `password` 可以正常注册
3. `/system/user/profile/updatePwd` 提交加密后的 `oldPassword``newPassword` 可以正常修改密码
4. `/system/user/resetPwd` 提交加密后的 `password` 可以正常重置密码
5. `/system/user` 提交加密后的 `password` 可以正常新增用户
6. 受控正式接口在密文非法时直接失败
7. `/login/test` 仍按现有方式运行,不受本次改动影响
## 14. 实施范围
- 前端:登录、注册、个人中心、用户管理相关 API 和密码加密工具
- 后端:登录、注册、个人中心、用户管理相关控制器和密码解密工具
- 配置:前端环境配置、后端应用配置
- 数据库:无表结构改动
本次属于接口边界增强,不涉及数据库结构和核心认证机制重构。