- 新增用户数据导出功能: * 支持导出当前查询条件下的数据 * 支持导出全部用户数据 * 支持下载用户导入模板 * 自动生成带时间戳的文件名 - 新增用户数据导入功能: * 拖拽上传Excel文件支持 * 文件类型和大小验证(.xlsx/.xls, 最大10MB) * 覆盖已存在数据选项 * 实时上传进度显示 * 详细的导入结果反馈 - 完善API接口: * downloadExcelTemplate: 下载Excel模板 * exportExcelData: 导出用户数据(支持查询参数) * importUserData: 导入用户数据(支持覆盖选项) - UI/UX优化: * 下拉菜单式导出按钮设计 * 专业的导入模态框界面 * 完善的错误处理和用户反馈 * 导入说明和操作指导 技术实现: - 使用Blob处理文件下载 - FormData处理文件上传 - Naive UI组件深度集成 - TypeScript类型安全保障
397 lines
8.3 KiB
Markdown
397 lines
8.3 KiB
Markdown
# 验证码API
|
||
|
||
## 概述
|
||
|
||
验证码模块提供图形验证码生成功能,支持PNG和GIF两种格式,用于防止恶意攻击和机器人注册。
|
||
|
||
## 接口列表
|
||
|
||
### 1. 生成PNG验证码
|
||
|
||
**接口地址**: `GET /captcha/png`
|
||
|
||
**接口描述**: 生成PNG格式的图形验证码
|
||
|
||
**是否需要认证**: 否
|
||
|
||
**请求参数**: 无
|
||
|
||
**响应示例**:
|
||
|
||
```json
|
||
{
|
||
"status": 200,
|
||
"msg": "SUCCESS",
|
||
"data": {
|
||
"uuid": "550e8400-e29b-41d4-a716-446655440000",
|
||
"base64": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAAAkCAYAAAB...",
|
||
"captchaText": "1234"
|
||
},
|
||
"traceId": "trace-123456"
|
||
}
|
||
```
|
||
|
||
**响应参数说明**:
|
||
|
||
| 参数名 | 类型 | 说明 |
|
||
|--------|------|------|
|
||
| uuid | String | 验证码唯一标识,用于后续验证 |
|
||
| base64 | String | 验证码图片Base64编码 |
|
||
| captchaText | String | 验证码文本(开发环境返回,生产环境不返回) |
|
||
|
||
**特性说明**:
|
||
|
||
- 验证码长度:4位数字
|
||
- 图片尺寸:102x38像素
|
||
- 有效期:5分钟
|
||
- 字体:随机字体
|
||
- 背景:随机背景色
|
||
- 干扰线:随机干扰线
|
||
|
||
**调用示例**:
|
||
|
||
```bash
|
||
curl -X GET \
|
||
http://localhost:18099/captcha/png \
|
||
-H 'Content-Type: application/json'
|
||
```
|
||
|
||
**前端使用示例**:
|
||
|
||
```javascript
|
||
// 获取验证码
|
||
function getCaptcha() {
|
||
fetch('/captcha/png')
|
||
.then(response => response.json())
|
||
.then(data => {
|
||
if (data.status === 200) {
|
||
// 显示验证码图片
|
||
document.getElementById('captchaImg').src = data.data.base64;
|
||
// 保存验证码UUID,用于登录时提交
|
||
document.getElementById('codeKey').value = data.data.uuid;
|
||
}
|
||
});
|
||
}
|
||
|
||
// 点击刷新验证码
|
||
document.getElementById('captchaImg').onclick = getCaptcha;
|
||
```
|
||
|
||
---
|
||
|
||
### 2. 生成GIF验证码
|
||
|
||
**接口地址**: `GET /captcha/gif`
|
||
|
||
**接口描述**: 生成GIF动画格式的图形验证码
|
||
|
||
**是否需要认证**: 否
|
||
|
||
**请求参数**: 无
|
||
|
||
**响应示例**:
|
||
|
||
```json
|
||
{
|
||
"status": 200,
|
||
"msg": "SUCCESS",
|
||
"data": {
|
||
"uuid": "550e8400-e29b-41d4-a716-446655440001",
|
||
"base64": "data:image/gif;base64,R0lGODlhZgAyAPcAAAAAAP///wAAAP...",
|
||
"captchaText": "5678"
|
||
},
|
||
"traceId": "trace-123456"
|
||
}
|
||
```
|
||
|
||
**响应参数说明**:
|
||
|
||
| 参数名 | 类型 | 说明 |
|
||
|--------|------|------|
|
||
| uuid | String | 验证码唯一标识,用于后续验证 |
|
||
| base64 | String | 验证码图片Base64编码 |
|
||
| captchaText | String | 验证码文本(开发环境返回,生产环境不返回) |
|
||
|
||
**特性说明**:
|
||
|
||
- 验证码长度:4位数字
|
||
- 图片尺寸:102x38像素
|
||
- 有效期:5分钟
|
||
- 动画效果:字符摆动动画
|
||
- 帧数:10帧
|
||
- 动画速度:100ms/帧
|
||
|
||
**调用示例**:
|
||
|
||
```bash
|
||
curl -X GET \
|
||
http://localhost:18099/captcha/gif \
|
||
-H 'Content-Type: application/json'
|
||
```
|
||
|
||
**前端使用示例**:
|
||
|
||
```javascript
|
||
// 获取GIF验证码
|
||
function getGifCaptcha() {
|
||
fetch('/captcha/gif')
|
||
.then(response => response.json())
|
||
.then(data => {
|
||
if (data.status === 200) {
|
||
// 显示验证码图片
|
||
document.getElementById('captchaImg').src = data.data.base64;
|
||
// 保存验证码UUID,用于登录时提交
|
||
document.getElementById('codeKey').value = data.data.uuid;
|
||
}
|
||
});
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 验证码配置
|
||
|
||
### 1. 验证码参数配置
|
||
|
||
```yaml
|
||
# application.yml
|
||
captcha:
|
||
# 验证码长度
|
||
length: 4
|
||
# 验证码宽度
|
||
width: 102
|
||
# 验证码高度
|
||
height: 38
|
||
# 验证码有效期(分钟)
|
||
timeout: 5
|
||
# 字体大小
|
||
font-size: 25
|
||
# 干扰线数量
|
||
line-count: 100
|
||
# 是否开启验证码
|
||
enabled: true
|
||
```
|
||
|
||
### 2. 验证码存储
|
||
|
||
- 验证码使用Redis存储
|
||
- Key格式:`captcha:uuid`
|
||
- 过期时间:5分钟自动删除
|
||
- 值存储:验证码文本(忽略大小写)
|
||
|
||
### 3. 验证码验证
|
||
|
||
```java
|
||
// 验证码验证逻辑
|
||
public boolean validateCaptcha(String uuid, String inputCode) {
|
||
// 从Redis获取验证码
|
||
String correctCode = redisTemplate.opsForValue().get("captcha:" + uuid);
|
||
|
||
if (correctCode == null) {
|
||
throw new BusinessException("验证码已过期");
|
||
}
|
||
|
||
// 不区分大小写验证
|
||
if (!correctCode.equalsIgnoreCase(inputCode)) {
|
||
throw new BusinessException("验证码错误");
|
||
}
|
||
|
||
// 验证成功后立即删除验证码(防止重复使用)
|
||
redisTemplate.delete("captcha:" + uuid);
|
||
|
||
return true;
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 安全特性
|
||
|
||
### 1. 防暴力破解
|
||
|
||
- 验证码一次性使用
|
||
- 验证后立即删除
|
||
- 5分钟自动过期
|
||
- 支持IP限制
|
||
|
||
### 2. 防机器识别
|
||
|
||
- 随机字体和颜色
|
||
- 随机背景和干扰线
|
||
- 字符位置随机偏移
|
||
- GIF动画增加识别难度
|
||
|
||
### 3. 防重放攻击
|
||
|
||
- 每次验证码都有唯一UUID
|
||
- 验证码使用后立即失效
|
||
- 不允许重复使用
|
||
|
||
## 错误处理
|
||
|
||
### 常见错误情况
|
||
|
||
| 错误场景 | 错误码 | 错误信息 |
|
||
|----------|--------|----------|
|
||
| 验证码过期 | 400 | 验证码已失效 |
|
||
| 验证码错误 | 400 | 验证码错误 |
|
||
| 验证码为空 | 400 | 请输入验证码 |
|
||
| UUID无效 | 400 | 验证码已失效 |
|
||
| 系统异常 | 500 | 验证码生成失败 |
|
||
|
||
### 错误响应示例
|
||
|
||
```json
|
||
{
|
||
"status": 400,
|
||
"msg": "验证码已失效",
|
||
"data": null,
|
||
"traceId": "trace-123456"
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 使用建议
|
||
|
||
### 1. 前端集成
|
||
|
||
```html
|
||
<!-- 验证码显示区域 -->
|
||
<div class="captcha-container">
|
||
<img id="captchaImg" src="" alt="验证码" onclick="refreshCaptcha()">
|
||
<input type="hidden" id="codeKey" value="">
|
||
<input type="text" id="securityCode" placeholder="请输入验证码">
|
||
<button type="button" onclick="refreshCaptcha()">刷新</button>
|
||
</div>
|
||
```
|
||
|
||
```javascript
|
||
// 初始化验证码
|
||
function initCaptcha() {
|
||
fetch('/captcha/png')
|
||
.then(response => response.json())
|
||
.then(data => {
|
||
if (data.status === 200) {
|
||
document.getElementById('captchaImg').src = data.data.base64;
|
||
document.getElementById('codeKey').value = data.data.uuid;
|
||
}
|
||
});
|
||
}
|
||
|
||
// 刷新验证码
|
||
function refreshCaptcha() {
|
||
initCaptcha();
|
||
}
|
||
|
||
// 页面加载时获取验证码
|
||
window.onload = initCaptcha;
|
||
```
|
||
|
||
### 2. 表单提交
|
||
|
||
```javascript
|
||
// 登录表单提交
|
||
function login() {
|
||
const formData = {
|
||
loginName: document.getElementById('loginName').value,
|
||
password: document.getElementById('password').value,
|
||
codeKey: document.getElementById('codeKey').value,
|
||
securityCode: document.getElementById('securityCode').value
|
||
};
|
||
|
||
fetch('/auth/login', {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/json'
|
||
},
|
||
body: JSON.stringify(formData)
|
||
})
|
||
.then(response => response.json())
|
||
.then(data => {
|
||
if (data.status === 200) {
|
||
// 登录成功
|
||
localStorage.setItem('token', data.data.tokenValue);
|
||
window.location.href = '/dashboard';
|
||
} else {
|
||
// 登录失败,刷新验证码
|
||
alert(data.msg);
|
||
refreshCaptcha();
|
||
}
|
||
});
|
||
}
|
||
```
|
||
|
||
### 3. 移动端适配
|
||
|
||
```css
|
||
/* 移动端验证码样式 */
|
||
@media (max-width: 768px) {
|
||
.captcha-container {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 10px;
|
||
}
|
||
|
||
#captchaImg {
|
||
width: 102px;
|
||
height: 38px;
|
||
cursor: pointer;
|
||
}
|
||
|
||
#securityCode {
|
||
width: 100px;
|
||
height: 38px;
|
||
}
|
||
}
|
||
```
|
||
|
||
## 性能优化
|
||
|
||
### 1. 缓存策略
|
||
|
||
- 验证码图片不缓存
|
||
- 验证码文本缓存5分钟
|
||
- 使用Redis集群提高性能
|
||
|
||
### 2. 并发控制
|
||
|
||
- 支持高并发验证码生成
|
||
- 每秒可生成1000+验证码
|
||
- 使用连接池管理Redis连接
|
||
|
||
### 3. 资源优化
|
||
|
||
- 图片大小优化(小于2KB)
|
||
- 内存使用优化
|
||
- 垃圾回收优化
|
||
|
||
## 监控和日志
|
||
|
||
### 1. 指标监控
|
||
|
||
- 验证码生成次数
|
||
- 验证码验证次数
|
||
- 验证码成功率
|
||
- 验证码过期率
|
||
|
||
### 2. 日志记录
|
||
|
||
- 验证码生成日志
|
||
- 验证码验证日志
|
||
- 异常错误日志
|
||
- 性能监控日志
|
||
|
||
### 3. 告警机制
|
||
|
||
- 验证码成功率过低告警
|
||
- 验证码生成异常告警
|
||
- Redis连接异常告警
|
||
|
||
## 注意事项
|
||
|
||
1. 生产环境不返回验证码文本
|
||
2. 验证码区分大小写(可配置)
|
||
3. 验证码只能使用一次
|
||
4. 建议定期清理过期验证码
|
||
5. 支持自定义验证码样式和难度 |