10 KiB
10 KiB
登录接口优化总结
🎯 优化目标
简化用户登录流程,使用手机号+短信验证码登录,若用户不存在则自动注册。
✅ 完成的优化
1. 简化LoginRequest
文件: backend-single/src/main/java/com/emotion/dto/request/LoginRequest.java
修改前:需要账号、密码、图形验证码、验证码key等字段
修改后:仅需2个字段
@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 新的登录流程
@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 自动注册用户
/**
* 自动注册用户(用于登录时用户不存在的情况)
*
* @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 生成随机密码
/**
* 生成随机密码
* 格式: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. 优化短信验证码发送
修改前:检查手机号是否已注册,已注册则抛出异常
修改后:根据是否已注册返回不同的提示信息
@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
/**
* 用户登录(简化版:手机号+验证码,不存在则自动注册)
*/
@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:获取短信验证码
请求:
curl -X GET "http://localhost:19089/api/auth/sms-code?phone=13900139000"
响应:
{
"code": 200,
"message": "验证码已发送",
"data": {
"code": "123456",
"expiresIn": 300,
"message": "验证码已发送,用于注册验证,有效期5分钟"
}
}
步骤2:登录(自动注册)
请求:
curl -X POST "http://localhost:19089/api/auth/login" \
-H "Content-Type: application/json" \
-d '{
"phone": "13900139000",
"smsCode": "123456"
}'
响应:
{
"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:获取短信验证码
请求:
curl -X GET "http://localhost:19089/api/auth/sms-code?phone=13900139000"
响应:
{
"code": 200,
"message": "验证码已发送",
"data": {
"code": "123456",
"expiresIn": 300,
"message": "验证码已发送,用于登录验证,有效期5分钟"
}
}
步骤2:登录
请求:
curl -X POST "http://localhost:19089/api/auth/login" \
-H "Content-Type: application/json" \
-d '{
"phone": "13900139000",
"smsCode": "123456"
}'
响应:
{
"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() 方法
当前代码:
// TODO: 接入真实的短信服务商(阿里云、腾讯云等)
// 目前使用固定验证码 123456
String code = DEFAULT_SMS_CODE;
后续改进:
// 生成随机6位数字验证码
String code = String.format("%06d", new Random().nextInt(1000000));
// 调用短信服务商API发送验证码
// 示例:阿里云短信服务
// smsService.sendSms(phone, code);
2. 生产环境优化
需要修改的地方:
-
移除响应中的验证码:
return SmsCodeResponse.builder() // .code(code) // 生产环境删除此行 .expiresIn((long) SMS_CODE_EXPIRE_MINUTES * 60) .message(message) .build(); -
添加发送频率限制:
- 同一手机号60秒内只能发送一次
- 同一IP每天最多发送10次
-
添加验证码尝试次数限制:
- 同一手机号最多尝试5次
- 超过次数后需要重新获取验证码
✅ 验证清单
- 编译成功,无错误
- LoginRequest简化为2个字段
- 实现自动注册逻辑
- 实现随机密码生成
- 优化短信验证码提示信息
- 更新Controller注解
- 测试新用户登录(自动注册)
- 测试已注册用户登录
- 添加详细的日志记录
🎉 总结
成功优化了登录接口,实现了以下目标:
- ✅ 简化登录流程 - 仅需手机号和短信验证码
- ✅ 自动注册机制 - 用户不存在时自动注册
- ✅ 智能提示信息 - 根据用户状态返回不同提示
- ✅ 无缝用户体验 - 无需区分注册和登录
- ✅ 良好的代码质量 - 清晰的注释、完善的日志、标准的异常处理
现在用户可以通过简单的2步完成登录或注册:
- 输入手机号获取验证码
- 输入验证码完成登录(不存在则自动注册)
登录成功后自动返回访问令牌和用户信息,用户体验大大提升!