docs: 添加登录验证码重构设计方案
将滑块验证改为数字+字母图形验证码,保持后端校验流程兼容。 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
b2d0c032df
commit
880006db5a
221
docs/superpowers/specs/2026-04-15-login-captcha-design.md
Normal file
221
docs/superpowers/specs/2026-04-15-login-captcha-design.md
Normal file
@ -0,0 +1,221 @@
|
|||||||
|
# 登录验证码重构设计方案
|
||||||
|
|
||||||
|
## 1. 背景与目标
|
||||||
|
|
||||||
|
### 现状
|
||||||
|
当前登录使用滑块拖动验证,用户体验不够友好,且代码实现较为复杂(纯前端拖动逻辑 + 后端 token 校验)。
|
||||||
|
|
||||||
|
### 目标
|
||||||
|
将滑块验证改为图形数字+字母验证码,提升用户体验,简化前端逻辑,保持后端安全校验流程不变。
|
||||||
|
|
||||||
|
### 范围
|
||||||
|
- 前端:`txw-mhzc-web` 登录页面(passwordlogin.vue、phonelogin.vue)
|
||||||
|
- 后端:`txw-sso` 服务新增验证码生成接口
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. 验证码规格
|
||||||
|
|
||||||
|
| 项目 | 规格 |
|
||||||
|
|------|------|
|
||||||
|
| 字符集 | 数字 0-9 + 大小写字母 A-Z/a-z |
|
||||||
|
| 长度 | 4 位 |
|
||||||
|
| 样式 | 扭曲变形文字 + 干扰线/噪点 |
|
||||||
|
| 图片尺寸 | 120 x 40 px |
|
||||||
|
| 格式 | Base64 PNG |
|
||||||
|
| 有效期 | Redis 存储,TTL 5 分钟 |
|
||||||
|
| 校验 | uuid + 验证码内容联合校验 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. 数据流
|
||||||
|
|
||||||
|
### 验证码获取流程
|
||||||
|
```
|
||||||
|
前端页面加载
|
||||||
|
→ POST /sso/verify/captcha
|
||||||
|
→ 后端生成 uuid + 验证码内容
|
||||||
|
→ 存入 Redis: captcha:{uuid} = 验证码内容, TTL 5min
|
||||||
|
→ 返回 { uuid, imageBase64 }
|
||||||
|
→ 前端渲染图片
|
||||||
|
```
|
||||||
|
|
||||||
|
### 登录流程
|
||||||
|
```
|
||||||
|
用户输入账号密码 + 验证码
|
||||||
|
→ POST /sso/auth/login
|
||||||
|
{
|
||||||
|
username: "xxx",
|
||||||
|
password: "xxx",
|
||||||
|
captchaVerification: "uuid",
|
||||||
|
captchaCode: "Kp7m"
|
||||||
|
}
|
||||||
|
→ 后端校验 captcha:{uuid} == captchaCode
|
||||||
|
→ 校验通过后继续账号密码验证
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. 前端改动
|
||||||
|
|
||||||
|
### 4.1 文件结构
|
||||||
|
|
||||||
|
| 文件 | 操作 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| `passwordlogin.vue` | 修改 | 注释滑块代码,新增验证码组件 |
|
||||||
|
| `phonelogin.vue` | 修改 | 同上 |
|
||||||
|
| `login.js` | 修改 | 新增 `getCaptcha()` API |
|
||||||
|
|
||||||
|
### 4.2 passwordlogin.vue 改动
|
||||||
|
|
||||||
|
**注释掉的代码(原滑块相关):**
|
||||||
|
- `mouseDown`, `mouseMoveFn`, `moseUpFn`, `successFunction` 方法 → 注释
|
||||||
|
- `maxWidth`, `beginClientX`, `mouseMoveState`, `confirmWords`, `confirmSuccess` 数据 → 注释
|
||||||
|
- `.drag` 模板区域 → 注释,替换为新验证码区域
|
||||||
|
- `mounted()` 中滑块初始化逻辑 → 注释
|
||||||
|
- `beforeDestroy()` 中的清理逻辑 → 注释
|
||||||
|
|
||||||
|
**新增代码:**
|
||||||
|
- 新增 `captchaCode` 表单字段
|
||||||
|
- 新增 `captchaUuid` 存储当前验证码 uuid
|
||||||
|
- 新增 `captchaImage` 存储验证码图片 base64
|
||||||
|
- 新增 `getCaptcha()` 方法调用后端接口
|
||||||
|
- 新增 `refreshCaptcha()` 刷新验证码方法
|
||||||
|
- 模板新增验证码图片 + 输入框 + 刷新按钮区域
|
||||||
|
|
||||||
|
### 4.3 验证码组件 UI(新增模板区域)
|
||||||
|
|
||||||
|
```html
|
||||||
|
<t-form-item name="captchaCode">
|
||||||
|
<div class="captcha-container">
|
||||||
|
<img :src="captchaImage" @click="refreshCaptcha" class="captcha-img" />
|
||||||
|
<t-input
|
||||||
|
v-model="loginForm.captchaCode"
|
||||||
|
placeholder="请输入验证码"
|
||||||
|
maxlength="4"
|
||||||
|
style="width: 120px"
|
||||||
|
/>
|
||||||
|
<span class="refresh-btn" @click="refreshCaptcha">刷新</span>
|
||||||
|
</div>
|
||||||
|
</t-form-item>
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4.4 样式新增
|
||||||
|
|
||||||
|
```css
|
||||||
|
.captcha-container {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
.captcha-img {
|
||||||
|
width: 120px;
|
||||||
|
height: 40px;
|
||||||
|
cursor: pointer;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
.refresh-btn {
|
||||||
|
color: #0052d9;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4.5 API 改动
|
||||||
|
|
||||||
|
**login.js 新增:**
|
||||||
|
```javascript
|
||||||
|
// 获取图形验证码
|
||||||
|
export const getCaptcha = () => {
|
||||||
|
return request({
|
||||||
|
url: '/sso/verify/captcha',
|
||||||
|
method: 'post'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. 后端改动
|
||||||
|
|
||||||
|
### 5.1 文件结构
|
||||||
|
|
||||||
|
| 文件 | 操作 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| `VerifyController.java` | 修改 | 新增 `/verify/captcha` 接口 |
|
||||||
|
| `VerifyService.java` | 修改 | 新增 `getCaptcha()` 接口定义 |
|
||||||
|
| `VerifyServiceImpl.java` | 修改 | 实现验证码生成(使用 Hutool 的 CaptchaUtil) |
|
||||||
|
| `AuthLoginReqVO.java` | 修改 | 新增 `captchaCode` 字段 |
|
||||||
|
| `AuthServiceImpl.java` | 修改 | login() 方法新增验证码校验逻辑 |
|
||||||
|
|
||||||
|
### 5.2 接口定义
|
||||||
|
|
||||||
|
**POST /sso/verify/captcha**
|
||||||
|
|
||||||
|
请求:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"remoteId": "IP+UserAgent hash"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
响应:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 0,
|
||||||
|
"data": {
|
||||||
|
"uuid": "abc123...",
|
||||||
|
"imageBase64": "data:image/png;base64,iVBORw0KGgo..."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5.3 Redis 存储结构
|
||||||
|
|
||||||
|
| Key | Value | TTL |
|
||||||
|
|-----|-------|-----|
|
||||||
|
| `captcha:{uuid}` | 验证码内容(如 "Kp7m") | 5 分钟 |
|
||||||
|
|
||||||
|
### 5.4 登录接口改动
|
||||||
|
|
||||||
|
`AuthLoginReqVO` 新增字段:
|
||||||
|
```java
|
||||||
|
private String captchaCode; // 用户输入的验证码
|
||||||
|
```
|
||||||
|
|
||||||
|
`AuthServiceImpl.login()` 改动:
|
||||||
|
```java
|
||||||
|
// 原有验证码 token 校验(滑块)
|
||||||
|
verifyService.checkVerifyToken(reqVO.getCaptchaVerification());
|
||||||
|
|
||||||
|
// 新增图形验证码校验
|
||||||
|
verifyService.checkCaptcha(reqVO.getCaptchaVerification(), reqVO.getCaptchaCode());
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. 安全考虑
|
||||||
|
|
||||||
|
1. **防暴力破解**:验证码校验失败后不暴露具体错误原因("验证码错误" vs "验证码已过期")
|
||||||
|
2. **一次性**:验证码验证成功后立即从 Redis 删除
|
||||||
|
3. **限频**:同一 IP 请求验证码频率限制(TODO)
|
||||||
|
4. **混淆**:图形验证码使用扭曲字体 + 干扰线,防止简单 OCR
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. 兼容性
|
||||||
|
|
||||||
|
- 原滑块相关代码**注释保留**,不删除,便于后续回滚
|
||||||
|
- `captchaVerification` 字段保留(复用为 uuid),登录参数结构兼容
|
||||||
|
- 后端兼容旧版滑块 token 校验逻辑(captcha check 可配置开关)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. 测试要点
|
||||||
|
|
||||||
|
1. 验证码图片正确渲染(扭曲字符可见)
|
||||||
|
2. 点击刷新生成新验证码
|
||||||
|
3. 输入正确验证码 + 正确账号密码 → 登录成功
|
||||||
|
4. 输入错误验证码 → 登录失败,提示"验证码错误"
|
||||||
|
5. 验证码过期(5分钟)→ 登录失败,提示"验证码已过期"
|
||||||
|
6. 滑块相关代码注释后,页面功能不受影响
|
||||||
Loading…
Reference in New Issue
Block a user