代码优化

This commit is contained in:
2025-10-13 10:43:08 +08:00
parent b6818b179c
commit bc3ed2d872
40 changed files with 3189 additions and 788 deletions
+396
View File
@@ -0,0 +1,396 @@
# 登录接口优化总结
## 🎯 优化目标
简化用户登录流程,使用手机号+短信验证码登录,若用户不存在则自动注册。
## ✅ 完成的优化
### 1. 简化LoginRequest
**文件**: `backend-single/src/main/java/com/emotion/dto/request/LoginRequest.java`
**修改前**:需要账号、密码、图形验证码、验证码key等字段
**修改后**:仅需2个字段
```java
@Data
@EqualsAndHashCode(callSuper = true)
public class LoginRequest extends BaseRequest {
/**
* 手机号
*/
@NotBlank(message = "手机号不能为空")
@Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号格式不正确")
private String phone;
/**
* 短信验证码
*/
@NotBlank(message = "验证码不能为空")
@Size(min = 6, max = 6, message = "验证码必须为6位")
private String smsCode;
}
```
### 2. 优化登录逻辑
**文件**: `backend-single/src/main/java/com/emotion/service/impl/AuthServiceImpl.java`
#### 2.1 新的登录流程
```java
@Override
public AuthResponse login(LoginRequest request) {
// 1. 验证短信验证码
if (!validateSmsCode(request.getPhone(), request.getSmsCode())) {
throw new CaptchaException("验证码错误或已过期");
}
// 2. 根据手机号查询用户
User user = userService.getByPhone(request.getPhone());
// 3. 如果用户不存在,则自动注册
if (user == null) {
log.info("用户不存在,自动注册: phone={}", request.getPhone());
user = autoRegisterUser(request.getPhone());
} else {
// 检查用户状态
if (user.getStatus() != 1) {
throw new AuthException("账号已被禁用");
}
log.info("用户登录: phone={}, userId={}", request.getPhone(), user.getId());
}
// 4. 生成令牌并返回
// ...
}
```
#### 2.2 自动注册用户
```java
/**
* 自动注册用户(用于登录时用户不存在的情况)
*
* @param phone 手机号
* @return 新创建的用户
*/
private User autoRegisterUser(String phone) {
// 生成随机用户名:开心 + 6位随机大小写字母和数字
String username = generateRandomUsername();
// 使用手机号作为账号
String account = phone;
// 生成随机密码(用户可以后续修改)
String randomPassword = generateRandomPassword();
// 创建用户
User user = userService.createUser(
account,
username,
randomPassword,
null, // 邮箱为空
phone
);
log.info("自动注册用户成功: phone={}, username={}, userId={}", phone, username, user.getId());
return user;
}
```
#### 2.3 生成随机密码
```java
/**
* 生成随机密码
* 格式:8位随机大小写字母和数字
*
* @return 随机密码
*/
private String generateRandomPassword() {
String chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
Random random = new Random();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 8; i++) {
int index = random.nextInt(chars.length());
sb.append(chars.charAt(index));
}
return sb.toString();
}
```
### 3. 优化短信验证码发送
**修改前**:检查手机号是否已注册,已注册则抛出异常
**修改后**:根据是否已注册返回不同的提示信息
```java
@Override
public SmsCodeResponse sendSmsCode(String phone) {
// 验证手机号格式
if (!StringUtils.hasText(phone) || !phone.matches("^1[3-9]\\d{9}$")) {
throw new BusinessException("手机号格式不正确");
}
// 检查手机号是否已注册,用于提示信息
boolean isRegistered = existsByPhone(phone);
String message;
if (isRegistered) {
message = "验证码已发送,用于登录验证,有效期" + SMS_CODE_EXPIRE_MINUTES + "分钟";
} else {
message = "验证码已发送,用于注册验证,有效期" + SMS_CODE_EXPIRE_MINUTES + "分钟";
}
// TODO: 接入真实的短信服务商(阿里云、腾讯云等)
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={}, isRegistered={}", phone, code, isRegistered);
// 构建响应
return SmsCodeResponse.builder()
.code(code) // 开发环境返回验证码,生产环境应该删除此行
.expiresIn((long) SMS_CODE_EXPIRE_MINUTES * 60)
.message(message)
.build();
}
```
### 4. 更新Controller注解
**文件**: `backend-single/src/main/java/com/emotion/controller/AuthController.java`
```java
/**
* 用户登录(简化版:手机号+验证码,不存在则自动注册)
*/
@PostMapping("/login")
@Operation(summary = "用户登录", description = "使用手机号和短信验证码登录,若用户不存在则自动注册")
public Result<AuthResponse> login(@Valid @RequestBody LoginRequest request) {
AuthResponse response = authService.login(request);
return Result.success("登录成功", response);
}
```
## 📊 优化对比
| 项目 | 优化前 | 优化后 |
|------|--------|--------|
| 必填字段 | 账号、密码、验证码、验证码key | 手机号、短信验证码 |
| 验证码类型 | 图形验证码 | 短信验证码 |
| 用户不存在 | 提示错误 | 自动注册 |
| 密码验证 | 需要 | 不需要 |
| 登录流程 | 复杂 | 简单快捷 |
## 🔧 核心特性
### 1. 简化登录流程
- ✅ 仅需2个字段:手机号、短信验证码
- ✅ 无需记住密码
- ✅ 用户不存在自动注册
- ✅ 自动生成随机用户名和密码
### 2. 智能提示信息
- ✅ 未注册用户:提示"用于注册验证"
- ✅ 已注册用户:提示"用于登录验证"
- ✅ 用户体验更友好
### 3. 自动注册机制
- ✅ 自动生成用户名:开心 + 6位随机字符
- ✅ 自动生成密码:8位随机字符
- ✅ 使用手机号作为账号
- ✅ 无缝登录体验
### 4. 安全性保障
- ✅ 手机号格式验证
- ✅ 短信验证码验证
- ✅ 验证码过期检查
- ✅ 验证码一次性使用
- ✅ 用户状态检查
## 🚀 使用示例
### 场景1:新用户首次登录(自动注册)
#### 步骤1:获取短信验证码
**请求**:
```bash
curl -X GET "http://localhost:19089/api/auth/sms-code?phone=13900139000"
```
**响应**:
```json
{
"code": 200,
"message": "验证码已发送",
"data": {
"code": "123456",
"expiresIn": 300,
"message": "验证码已发送,用于注册验证,有效期5分钟"
}
}
```
#### 步骤2:登录(自动注册)
**请求**:
```bash
curl -X POST "http://localhost:19089/api/auth/login" \
-H "Content-Type: application/json" \
-d '{
"phone": "13900139000",
"smsCode": "123456"
}'
```
**响应**:
```json
{
"code": 200,
"message": "登录成功",
"data": {
"accessToken": "eyJhbGciOiJIUzUxMiJ9...",
"refreshToken": "eyJhbGciOiJIUzUxMiJ9...",
"expiresIn": 86400,
"userInfo": {
"id": "f361c8648378565a91c6d799d641741f",
"account": "13900139000",
"username": "开心4FhbOl",
"nickname": "开心4FhbOl",
"phone": "13900139000",
"memberLevel": "free"
},
"loginTime": "2025-10-06 23:14:57"
}
}
```
### 场景2:已注册用户登录
#### 步骤1:获取短信验证码
**请求**:
```bash
curl -X GET "http://localhost:19089/api/auth/sms-code?phone=13900139000"
```
**响应**:
```json
{
"code": 200,
"message": "验证码已发送",
"data": {
"code": "123456",
"expiresIn": 300,
"message": "验证码已发送,用于登录验证,有效期5分钟"
}
}
```
#### 步骤2:登录
**请求**:
```bash
curl -X POST "http://localhost:19089/api/auth/login" \
-H "Content-Type: application/json" \
-d '{
"phone": "13900139000",
"smsCode": "123456"
}'
```
**响应**:
```json
{
"code": 200,
"message": "登录成功",
"data": {
"accessToken": "eyJhbGciOiJIUzUxMiJ9...",
"refreshToken": "eyJhbGciOiJIUzUxMiJ9...",
"expiresIn": 86400,
"userInfo": {
"id": "f361c8648378565a91c6d799d641741f",
"account": "13900139000",
"username": "开心4FhbOl",
"nickname": "开心4FhbOl",
"phone": "13900139000",
"memberLevel": "free"
},
"loginTime": "2025-10-06 23:15:18"
}
}
```
## 📝 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(message)
.build();
```
2. **添加发送频率限制**
- 同一手机号60秒内只能发送一次
- 同一IP每天最多发送10次
3. **添加验证码尝试次数限制**
- 同一手机号最多尝试5次
- 超过次数后需要重新获取验证码
## ✅ 验证清单
- [x] 编译成功,无错误
- [x] LoginRequest简化为2个字段
- [x] 实现自动注册逻辑
- [x] 实现随机密码生成
- [x] 优化短信验证码提示信息
- [x] 更新Controller注解
- [x] 测试新用户登录(自动注册)
- [x] 测试已注册用户登录
- [x] 添加详细的日志记录
## 🎉 总结
成功优化了登录接口,实现了以下目标:
1.**简化登录流程** - 仅需手机号和短信验证码
2.**自动注册机制** - 用户不存在时自动注册
3.**智能提示信息** - 根据用户状态返回不同提示
4.**无缝用户体验** - 无需区分注册和登录
5.**良好的代码质量** - 清晰的注释、完善的日志、标准的异常处理
现在用户可以通过简单的2步完成登录或注册:
1. 输入手机号获取验证码
2. 输入验证码完成登录(不存在则自动注册)
登录成功后自动返回访问令牌和用户信息,用户体验大大提升!