Files
happy-life-star/AUTH_REGISTER_OPTIMIZATION.md
T
2025-10-13 10:43:08 +08:00

434 lines
11 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. 简化RegisterRequest
**文件**: `backend-single/src/main/java/com/emotion/dto/request/RegisterRequest.java`
**修改前**:需要账号、密码、确认密码、用户名、昵称、邮箱、手机号、图形验证码等多个字段
**修改后**:仅需3个字段
```java
@Data
@EqualsAndHashCode(callSuper = true)
public class RegisterRequest extends BaseRequest {
/**
* 手机号(作为账号)
*/
@NotBlank(message = "手机号不能为空")
@Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号格式不正确")
private String phone;
/**
* 密码
*/
@NotBlank(message = "密码不能为空")
@Size(min = 6, max = 20, message = "密码长度必须在6-20个字符之间")
private String password;
/**
* 短信验证码
*/
@NotBlank(message = "验证码不能为空")
@Size(min = 6, max = 6, message = "验证码必须为6位")
private String smsCode;
}
```
### 2. 新增SmsCodeResponse
**文件**: `backend-single/src/main/java/com/emotion/dto/response/SmsCodeResponse.java`
```java
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class SmsCodeResponse {
/**
* 验证码(开发环境返回,生产环境不返回)
*/
private String code;
/**
* 过期时间(秒)
*/
private Long expiresIn;
/**
* 提示信息
*/
private String message;
}
```
### 3. 新增获取短信验证码接口
**文件**: `backend-single/src/main/java/com/emotion/controller/AuthController.java`
```java
/**
* 获取短信验证码(用于注册)
*/
@GetMapping("/sms-code")
@Operation(summary = "获取短信验证码", description = "用于注册时的短信验证码")
public Result<SmsCodeResponse> getSmsCode(
@Parameter(description = "手机号", required = true)
@RequestParam String phone) {
SmsCodeResponse response = authService.sendSmsCode(phone);
return Result.success("验证码已发送", response);
}
```
**接口地址**: `GET /api/auth/sms-code?phone=13800138000`
**响应示例**:
```json
{
"code": 200,
"message": "验证码已发送",
"data": {
"code": "123456",
"expiresIn": 300,
"message": "验证码已发送,有效期5分钟"
}
}
```
### 4. 优化注册接口逻辑
**文件**: `backend-single/src/main/java/com/emotion/service/impl/AuthServiceImpl.java`
#### 4.1 新增常量定义
```java
private static final String SMS_CODE_PREFIX = "sms_code:";
private static final int SMS_CODE_EXPIRE_MINUTES = 5;
private static final String DEFAULT_SMS_CODE = "123456";
```
#### 4.2 简化注册逻辑
```java
@Override
public AuthResponse register(RegisterRequest request) {
// 1. 验证短信验证码
if (!validateSmsCode(request.getPhone(), request.getSmsCode())) {
throw new CaptchaException("验证码错误或已过期");
}
// 2. 检查手机号是否已存在
if (userService.getByPhone(request.getPhone()) != null) {
throw new BusinessException("手机号已被注册");
}
// 3. 生成随机用户名:开心 + 6位随机大小写字母和数字
String username = generateRandomUsername();
// 4. 使用手机号作为账号
String account = request.getPhone();
// 5. 创建用户
User user = userService.createUser(
account,
username,
request.getPassword(),
null, // 邮箱为空
request.getPhone()
);
// 6. 生成令牌并返回
// ...
}
```
#### 4.3 实现短信验证码发送
```java
@Override
public SmsCodeResponse sendSmsCode(String phone) {
// 验证手机号格式
if (!StringUtils.hasText(phone) || !phone.matches("^1[3-9]\\d{9}$")) {
throw new BusinessException("手机号格式不正确");
}
// 检查手机号是否已注册
if (existsByPhone(phone)) {
throw new BusinessException("该手机号已被注册");
}
// TODO: 接入真实的短信服务商(阿里云、腾讯云等)
// 目前使用固定验证码 123456
String code = DEFAULT_SMS_CODE;
// 将验证码存储到Redis,有效期5分钟
String key = SMS_CODE_PREFIX + phone;
redisTemplate.opsForValue().set(key, code, SMS_CODE_EXPIRE_MINUTES, TimeUnit.MINUTES);
log.info("发送短信验证码: phone={}, code={}", phone, code);
// 构建响应
return SmsCodeResponse.builder()
.code(code) // 开发环境返回验证码,生产环境应该删除此行
.expiresIn((long) SMS_CODE_EXPIRE_MINUTES * 60)
.message("验证码已发送,有效期" + SMS_CODE_EXPIRE_MINUTES + "分钟")
.build();
}
```
#### 4.4 实现短信验证码校验
```java
@Override
public boolean validateSmsCode(String phone, String code) {
if (!StringUtils.hasText(phone) || !StringUtils.hasText(code)) {
return false;
}
String key = SMS_CODE_PREFIX + phone;
String storedCode = (String) redisTemplate.opsForValue().get(key);
if (storedCode == null) {
log.warn("短信验证码不存在或已过期: phone={}", phone);
return false;
}
boolean isValid = storedCode.equals(code);
// 验证成功后删除验证码(一次性使用)
if (isValid) {
redisTemplate.delete(key);
log.info("短信验证码验证成功: phone={}", phone);
} else {
log.warn("短信验证码错误: phone={}, expected={}, actual={}", phone, storedCode, code);
}
return isValid;
}
```
#### 4.5 实现随机用户名生成
```java
/**
* 生成随机用户名
* 格式:开心 + 6位随机大小写字母和数字
*
* @return 随机用户名
*/
private String generateRandomUsername() {
String chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
Random random = new Random();
StringBuilder sb = new StringBuilder("开心");
for (int i = 0; i < 6; i++) {
int index = random.nextInt(chars.length());
sb.append(chars.charAt(index));
}
return sb.toString();
}
```
**用户名示例**:
- 开心A3bC9z
- 开心X7yK2m
- 开心P1qW5n
### 5. 更新AuthService接口
**文件**: `backend-single/src/main/java/com/emotion/service/AuthService.java`
新增方法定义:
```java
/**
* 发送短信验证码
*
* @param phone 手机号
* @return 短信验证码响应
*/
SmsCodeResponse sendSmsCode(String phone);
/**
* 验证短信验证码
*
* @param phone 手机号
* @param code 验证码
* @return 是否验证成功
*/
boolean validateSmsCode(String phone, String code);
```
## 📊 优化对比
| 项目 | 优化前 | 优化后 |
|------|--------|--------|
| 必填字段 | 账号、密码、确认密码、验证码、验证码key | 手机号、密码、短信验证码 |
| 验证码类型 | 图形验证码 | 短信验证码 |
| 用户名生成 | 手动输入或使用账号 | 自动生成(开心+6位随机) |
| 账号 | 手动输入 | 自动使用手机号 |
| 邮箱 | 可选输入 | 不需要 |
| 昵称 | 可选输入 | 自动使用用户名 |
## 🔧 核心特性
### 1. 简化注册流程
- ✅ 仅需3个字段:手机号、密码、短信验证码
- ✅ 自动生成用户名:开心 + 6位随机字符
- ✅ 手机号作为账号
- ✅ 移除了确认密码、邮箱、昵称等非必要字段
### 2. 短信验证码机制
- ✅ 默认验证码:123456(开发环境)
- ✅ 有效期:5分钟
- ✅ 一次性使用:验证成功后自动删除
- ✅ Redis存储:支持分布式部署
- ✅ TODO标记:预留真实短信服务接入点
### 3. 安全性保障
- ✅ 手机号格式验证
- ✅ 手机号唯一性检查
- ✅ 验证码过期检查
- ✅ 验证码一次性使用
- ✅ 密码加密存储
### 4. 用户体验优化
- ✅ 注册流程简单快捷
- ✅ 自动生成友好的用户名
- ✅ 清晰的错误提示
- ✅ 完整的API文档(Swagger
## 🚀 使用示例
### 1. 获取短信验证码
**请求**:
```bash
curl -X GET "http://localhost:19089/api/auth/sms-code?phone=13800138000"
```
**响应**:
```json
{
"code": 200,
"message": "验证码已发送",
"data": {
"code": "123456",
"expiresIn": 300,
"message": "验证码已发送,有效期5分钟"
}
}
```
### 2. 用户注册
**请求**:
```bash
curl -X POST "http://localhost:19089/api/auth/register" \
-H "Content-Type: application/json" \
-d '{
"phone": "13800138000",
"password": "password123",
"smsCode": "123456"
}'
```
**响应**:
```json
{
"code": 200,
"message": "注册成功",
"data": {
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"expiresIn": 86400,
"userInfo": {
"id": "1844234567890123456",
"account": "13800138000",
"username": "开心A3bC9z",
"nickname": "开心A3bC9z",
"phone": "13800138000",
"memberLevel": "free",
"status": 1
},
"loginTime": "2025-10-06 21:49:33"
}
}
```
## 📝 TODO事项
### 1. 接入真实短信服务
**位置**: `AuthServiceImpl.sendSmsCode()` 方法
**当前代码**:
```java
// TODO: 接入真实的短信服务商(阿里云、腾讯云等)
// 目前使用固定验证码 123456
String code = DEFAULT_SMS_CODE;
```
**后续改进**:
```java
// 生成随机6位数字验证码
String code = String.format("%06d", new Random().nextInt(1000000));
// 调用短信服务商API发送验证码
// 示例:阿里云短信服务
// smsService.sendSms(phone, code);
```
### 2. 生产环境优化
**需要修改的地方**:
1. **移除响应中的验证码**
```java
return SmsCodeResponse.builder()
// .code(code) // 生产环境删除此行
.expiresIn((long) SMS_CODE_EXPIRE_MINUTES * 60)
.message("验证码已发送,有效期" + SMS_CODE_EXPIRE_MINUTES + "分钟")
.build();
```
2. **添加发送频率限制**
- 同一手机号60秒内只能发送一次
- 同一IP每天最多发送10次
3. **添加验证码尝试次数限制**
- 同一手机号最多尝试5次
- 超过次数后需要重新获取验证码
## ✅ 验证清单
- [x] 编译成功,无错误
- [x] RegisterRequest简化为3个字段
- [x] 新增SmsCodeResponse响应类
- [x] 新增获取短信验证码接口
- [x] 实现短信验证码发送逻辑
- [x] 实现短信验证码校验逻辑
- [x] 实现随机用户名生成
- [x] 优化注册接口逻辑
- [x] 添加Swagger API文档注解
- [x] 添加详细的日志记录
## 🎉 总结
成功优化了注册接口,实现了以下目标:
1.**简化注册流程** - 仅需手机号、密码和短信验证码
2.**自动生成用户名** - 开心 + 6位随机大小写字母和数字
3.**短信验证码机制** - 默认123456,预留真实短信服务接入点
4.**完整的校验逻辑** - 手机号格式、唯一性、验证码有效性
5.**良好的代码质量** - 清晰的注释、完善的日志、标准的异常处理
现在用户可以通过简单的3步完成注册:
1. 输入手机号获取验证码
2. 输入密码和验证码
3. 自动生成用户名并完成注册
注册成功后自动登录,返回访问令牌和用户信息!