|
@@ -0,0 +1,238 @@
|
|
|
+package com.example.course.user.service.impl;
|
|
|
+
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
|
|
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|
|
+import com.example.course.user.dto.LoginDto;
|
|
|
+import com.example.course.user.dto.PhoneDto;
|
|
|
+import com.example.course.user.dto.RegistDto;
|
|
|
+import com.example.course.user.pojo.User;
|
|
|
+import com.example.course.user.service.UserService;
|
|
|
+import com.example.course.user.mapper.UserMapper;
|
|
|
+import com.example.course.utils.*;
|
|
|
+import org.slf4j.Logger;
|
|
|
+import org.slf4j.LoggerFactory;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+import org.springframework.util.DigestUtils;
|
|
|
+import org.springframework.util.StringUtils;
|
|
|
+
|
|
|
+import java.nio.charset.StandardCharsets;
|
|
|
+import java.util.HashMap;
|
|
|
+import java.util.Map;
|
|
|
+import java.util.UUID;
|
|
|
+
|
|
|
+/**
|
|
|
+ * @author 张大宇
|
|
|
+ * @description 针对表【user(用户信息表)】的数据库操作Service实现
|
|
|
+ * @createDate 2025-05-19 18:56:29
|
|
|
+ */
|
|
|
+@Service
|
|
|
+public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
|
|
|
+
|
|
|
+ private static final Logger logger = LoggerFactory.getLogger(UserService.class);
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private UserMapper userMapper;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private RedisClient redisClient;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 统一获取验证码方法
|
|
|
+ * @param phone 手机号
|
|
|
+ * @return 验证码
|
|
|
+ */
|
|
|
+ private Object getVerificationCode(String phone) {
|
|
|
+ String key = "CODE:" + phone;
|
|
|
+ return redisClient.get(key);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 统一删除验证码方法
|
|
|
+ * @param phone 手机号
|
|
|
+ */
|
|
|
+ private void deleteVerificationCode(String phone) {
|
|
|
+ String key = "CODE:" + phone;
|
|
|
+ redisClient.del(key);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 账号密码登录
|
|
|
+ * @param loginDto
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public ResponseResult login(LoginDto loginDto) {
|
|
|
+ if (StringUtils.isEmpty(loginDto.getUsername()) || StringUtils.isEmpty(loginDto.getPassword())) {
|
|
|
+ return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
|
|
|
+ }
|
|
|
+ QueryWrapper<User> wrapper = new QueryWrapper<>();
|
|
|
+ User selectOne = userMapper.selectOne(wrapper.lambda().eq(User::getUsername, loginDto.getUsername()));
|
|
|
+ if (selectOne == null) {
|
|
|
+ return ResponseResult.errorResult(AppHttpCodeEnum.AP_USER_DATA_NOT_EXIST);
|
|
|
+ }
|
|
|
+
|
|
|
+ String salt = selectOne.getSale();
|
|
|
+ String password = loginDto.getPassword();
|
|
|
+ String md5 = DigestUtils.md5DigestAsHex((password + salt).getBytes(StandardCharsets.UTF_8));
|
|
|
+ if (!md5.equals(selectOne.getPassword())) {
|
|
|
+ return ResponseResult.errorResult(202, "密码错误");
|
|
|
+ }
|
|
|
+ String token = AppJwtUtil.getToken(selectOne.getId().longValue());
|
|
|
+ redisClient.set("token", token);
|
|
|
+ HashMap<String, String> map = new HashMap<>();
|
|
|
+ map.put("token", token);
|
|
|
+ map.put("name", selectOne.getUsername());
|
|
|
+ return ResponseResult.okResult(map);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 手机号验证码登录
|
|
|
+ * @param phoneDto
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public ResponseResult phonelogin(PhoneDto phoneDto) {
|
|
|
+ // 参数校验
|
|
|
+ if (phoneDto.getPhone() == null ||!phoneDto.getPhone().matches("1[3-9]\\d{9}")) {
|
|
|
+ return ResponseResult.errorResult(400, "手机号格式错误");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取验证码
|
|
|
+ Object codeObj = getVerificationCode(phoneDto.getPhone());
|
|
|
+ if (codeObj == null) {
|
|
|
+ logger.info("手机号 {} 验证码已过期", phoneDto.getPhone());
|
|
|
+ return ResponseResult.errorResult(201, "验证码已过期");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 验证验证码
|
|
|
+ String codeStr = String.valueOf(codeObj);
|
|
|
+ String userCode = phoneDto.getCode();
|
|
|
+ if (userCode == null ||!userCode.matches("\\d{4}")) {
|
|
|
+ logger.info("手机号 {} 输入的验证码格式错误", phoneDto.getPhone());
|
|
|
+ return ResponseResult.errorResult(201, "验证码格式错误");
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!codeStr.equals(userCode)) {
|
|
|
+ logger.info("手机号 {} 验证码错误,Redis: {}, 用户输入: {}",
|
|
|
+ phoneDto.getPhone(), codeStr, userCode);
|
|
|
+ return ResponseResult.errorResult(201, "验证码错误");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 验证通过后删除验证码
|
|
|
+ deleteVerificationCode(phoneDto.getPhone());
|
|
|
+
|
|
|
+ // 查询用户是否存在
|
|
|
+ QueryWrapper<User> queryWrapper = new QueryWrapper<>();
|
|
|
+ queryWrapper.lambda().eq(User::getPhone, phoneDto.getPhone());
|
|
|
+ User existingUser = userMapper.selectOne(queryWrapper);
|
|
|
+
|
|
|
+ // 用户不存在,创建新用户
|
|
|
+ if (existingUser == null) {
|
|
|
+ User newUser = new User();
|
|
|
+ newUser.setId(SnowflakeIdGenerator.getSnowId());
|
|
|
+ newUser.setPhone(phoneDto.getPhone());
|
|
|
+
|
|
|
+ // 生成随机用户名(格式:用户+时间戳后4位)
|
|
|
+ String randomUsername = "用户" + System.currentTimeMillis() % 10000;
|
|
|
+ newUser.setUsername(randomUsername);
|
|
|
+
|
|
|
+ try {
|
|
|
+ userMapper.insert(newUser);
|
|
|
+ logger.info("新用户创建成功,ID:{},手机号:{}", newUser.getId(), phoneDto.getPhone());
|
|
|
+ return generateLoginResponse(newUser);
|
|
|
+ } catch (Exception e) {
|
|
|
+ logger.error("用户创建失败,手机号:{}", phoneDto.getPhone(), e);
|
|
|
+ return ResponseResult.errorResult(500, "用户注册失败,请重试");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 用户已存在,直接登录
|
|
|
+ logger.info("用户登录成功,ID:{},手机号:{}", existingUser.getId(), phoneDto.getPhone());
|
|
|
+ return generateLoginResponse(existingUser);
|
|
|
+ }
|
|
|
+
|
|
|
+ private ResponseResult generateLoginResponse(User user) {
|
|
|
+ // 存储用户ID到Redis
|
|
|
+ String uidKey = "USER:UID:" + user.getId();
|
|
|
+ redisClient.set(uidKey, user.getId());
|
|
|
+ redisClient.expire(uidKey, 3600); // 1小时有效期
|
|
|
+
|
|
|
+ // 生成JWT Token
|
|
|
+ String token = AppJwtUtil.getToken(user.getId());
|
|
|
+
|
|
|
+ // 存储Token到Redis(可选,用于Token黑名单等场景)
|
|
|
+ redisClient.set("token", token);
|
|
|
+ redisClient.expire(token, 3600);
|
|
|
+
|
|
|
+
|
|
|
+ // 返回结果
|
|
|
+ Map<String, Object> resultMap = new HashMap<>();
|
|
|
+ resultMap.put("token", token);
|
|
|
+ resultMap.put("name", user.getUsername());
|
|
|
+ resultMap.put("userId", user.getId());
|
|
|
+
|
|
|
+ return ResponseResult.okResult(resultMap);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 注册
|
|
|
+ * @param registDto
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public ResponseResult regist(RegistDto registDto) {
|
|
|
+ // 获取验证码
|
|
|
+ Object code = getVerificationCode(registDto.getPhone());
|
|
|
+ if (code == null) {
|
|
|
+ return new ResponseResult(201, "验证码已过期");
|
|
|
+ }
|
|
|
+ String codeStr = String.valueOf(code);
|
|
|
+ String userCode = registDto.getCode();
|
|
|
+ if (!codeStr.equals(userCode)) {
|
|
|
+ return new ResponseResult(201, "验证码错误");
|
|
|
+ }
|
|
|
+ // 删除已使用的验证码
|
|
|
+ deleteVerificationCode(registDto.getPhone());
|
|
|
+
|
|
|
+ // 先判断账号是否存在
|
|
|
+ QueryWrapper<User> usernameWrapper = new QueryWrapper<>();
|
|
|
+ usernameWrapper.lambda().eq(User::getUsername, registDto.getUsername());
|
|
|
+ User user1 = userMapper.selectOne(usernameWrapper);
|
|
|
+ if (user1 != null) {
|
|
|
+ return ResponseResult.errorResult(AppHttpCodeEnum.DATA_EXIST, "账号已存在");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 判断手机号是否存在
|
|
|
+ QueryWrapper<User> phoneWrapper = new QueryWrapper<>();
|
|
|
+ phoneWrapper.lambda().eq(User::getPhone, registDto.getPhone());
|
|
|
+ User user2 = userMapper.selectOne(phoneWrapper);
|
|
|
+ if (user2 != null) {
|
|
|
+ return ResponseResult.errorResult(AppHttpCodeEnum.DATA_EXIST, "手机号已存在");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 注册用户
|
|
|
+ User user = new User();
|
|
|
+ user.setUsername(registDto.getUsername());
|
|
|
+ user.setPhone(registDto.getPhone());
|
|
|
+ String salt = UUID.randomUUID().toString();
|
|
|
+ user.setSale(salt);
|
|
|
+ user.setPassword(DigestUtils.md5DigestAsHex((registDto.getPassword() + salt).getBytes(StandardCharsets.UTF_8)));
|
|
|
+ user.setId(SnowflakeIdGenerator.getSnowId());
|
|
|
+
|
|
|
+ userMapper.insert(user);
|
|
|
+ redisClient.set("uid", user.getId());
|
|
|
+ redisClient.expire("uid", 60 * 60);
|
|
|
+
|
|
|
+ return ResponseResult.okResult(200, "注册成功");
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public ResponseResult exit() {
|
|
|
+ if (redisClient.exists("uid")) {
|
|
|
+ redisClient.del("uid");
|
|
|
+ return ResponseResult.okResult(200, "退出成功");
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+}
|