diff --git a/ai_knowledge_base_v2/development_records/2026-07-09-user-login-graphic-captcha.md b/ai_knowledge_base_v2/development_records/2026-07-09-user-login-graphic-captcha.md new file mode 100644 index 0000000..62f2409 --- /dev/null +++ b/ai_knowledge_base_v2/development_records/2026-07-09-user-login-graphic-captcha.md @@ -0,0 +1,69 @@ +# 用户端短信登录增加图形验证码 + +日期:2026-07-09 + +## 需求背景 + +用户端当前发送短信验证码前只校验手机号格式和学员名单。为了减少短信接口被刷、验证码被滥用,需要在发送短信验证码前增加图形验证码。当前业务规则仍然保持:只有后台学员名单中存在且启用的手机号才允许发送短信验证码和登录。 + +## 本次目标 + +1. 用户端登录页增加图形验证码输入。 +2. 发送短信验证码前必须先通过图形验证码校验。 +3. 发送短信验证码前继续校验手机号是否存在于后台学员名单。 +4. 手机号不存在时,前端弹出/展示明确错误,用户能直接看到。 +5. 图形验证码部署后显示效果要和开发环境尽量一致。 + +## 字体与部署决策 + +- 后端生成 PNG 图形验证码,不依赖浏览器字体渲染。 +- 使用 Pillow 生成图片。 +- Docker 镜像安装 `fonts-dejavu-core`,避免容器环境缺少字体后退回默认小字体。 +- 后端字体加载采用多路径 fallback,优先使用 `DejaVuSans-Bold.ttf`。 +- 文本居中使用 `textbbox` 计算,避免不同字体下位置偏移。 +- 如果字体确实无法加载,会回退到 Pillow 默认字体,并记录日志;但生产镜像应通过 Dockerfile 保证 DejaVu 字体可用。 + +## 接口设计 + +### 获取图形验证码 + +`GET /api/auth/captcha` + +返回: + +```json +{ + "captchaId": "uuid", + "imageBase64": "data:image/png;base64,...", + "expiresInSeconds": 300 +} +``` + +### 发送短信验证码 + +`POST /api/auth/sms/send` + +请求体新增: + +```json +{ + "phone": "13800000000", + "captchaId": "uuid", + "captchaCode": "1234" +} +``` + +后端校验顺序: + +1. 校验图形验证码。 +2. 校验手机号是否存在于后台学员名单,且账号状态允许登录。 +3. 发送短信验证码。 + +## 验收标准 + +- 登录页打开时自动加载图形验证码。 +- 点击图形验证码可刷新。 +- 图形验证码为空或错误时,不能发送短信验证码。 +- 手机号不存在时,发送短信验证码接口返回“手机号不在学员名单中,请联系管理员”,前端可见。 +- 图形验证码通过且手机号存在时,mock 短信仍可正常发送。 +- Docker 环境中图形验证码字体清晰,不能退化成过小或错位的默认字体。