docs: 添加登录验证码重构设计方案

将滑块验证改为数字+字母图形验证码,保持后端校验流程兼容。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
liulujian 2026-04-15 15:22:47 +08:00
parent b2d0c032df
commit 880006db5a

View 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. 滑块相关代码注释后,页面功能不受影响