package com.example.demo.user.service.impl; import cn.hutool.core.util.IdUtil; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.example.demo.common.utils.Md5Util; import com.example.demo.common.utils.RedisClient; import com.example.demo.common.utils.TokenUtils; import com.example.demo.user.domain.User; import com.example.demo.user.dto.LoginDto; import com.example.demo.user.dto.PerfectDto; import com.example.demo.user.dto.PhoneDto; import com.example.demo.user.dto.RegisterDto; import com.example.demo.user.service.UserService; import com.example.demo.user.dao.UserMapper; import com.example.demo.user.vo.ResultVo; import lombok.extern.slf4j.Slf4j; import org.redisson.api.RLock; import org.redisson.api.RedissonClient; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Service; import java.util.UUID; import java.util.concurrent.TimeUnit; /** * @author 徐乐 * @description 针对表【user(用户基础信息表)】的数据库操作Service实现 * @createDate 2025-06-04 17:31:35 */ @Slf4j @Service public class UserServiceImpl extends ServiceImpl implements UserService{ @Autowired private UserMapper userMapper; @Autowired private RedissonClient redissonClient; @Autowired private RedisTemplate redisTemplate; @Autowired private RedisClient redisClient; @Override public ResultVo register(RegisterDto dto) { // 获取验证码 Object code = getVerificationCode(dto.getPhone()); if (code == null) { return ResultVo.error(201, "验证码已过期"); } String codeStr = String.valueOf(code); String userCode = dto.getCode(); if (!codeStr.equals(userCode)) { return ResultVo.error(202, "验证码错误"); } // 删除已使用的验证码 deleteVerificationCode(dto.getPhone()); QueryWrapper userQueryWrapper = new QueryWrapper<>(); userQueryWrapper.eq("phone", dto.getPhone()); log.info("加锁"); RLock lock = redissonClient.getLock(dto.getPhone()); try { log.info("获取锁"); boolean lockSuccess = lock.tryLock(3, TimeUnit.SECONDS); if (!lockSuccess) { throw new RuntimeException("操作频繁,请稍后再试"); } User user = userMapper.selectOne(userQueryWrapper); if (user != null) { return ResultVo.error("用户已存在"); } log.info("注册"); User u = new User(); u.setId(IdUtil.getSnowflake().nextId()); //生成盐值 String uuid = UUID.randomUUID().toString().replaceAll("-", ""); u.setSalt(uuid); //获取密码 String password = dto.getPassword(); //加密 String md5Password = Md5Util.MD5(uuid + password); u.setPassword(md5Password); u.setPhone(dto.getPhone()); u.setEmail(u.getPhone()+"@example.com"); userMapper.insert(u); return ResultVo.success("注册成功"); } catch (Exception e) { e.printStackTrace(); throw new RuntimeException("注册过程中出现异常,请稍后再试"); } finally { if (lock.isLocked() && lock.isHeldByCurrentThread()) { log.info("释放锁"); lock.unlock(); } } } /** * 统一获取验证码方法 * @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); } @Override public ResultVo login(LoginDto dto) { QueryWrapper userQueryWrapper = new QueryWrapper<>(); userQueryWrapper.eq("phone",dto.getPhone()); User user = userMapper.selectOne(userQueryWrapper); if (user==null){ return ResultVo.error("用户不存在"); } //获取盐值 String salt = user.getSalt(); //获取密码 String password = dto.getPassword(); //加密 String encryptedPassword = Md5Util.MD5(salt + password); if (encryptedPassword.equals(user.getPassword())){ String token = TokenUtils.createJwtToken(user.getId().toString()); // 使用用户ID作为键名的一部分 redisTemplate.opsForValue().set("userToken:" + user.getId(), token); redisTemplate.expire("userToken:" + user.getId(), 24, TimeUnit.HOURS); // 设置24小时过期 return ResultVo.success(token); } return ResultVo.error("用户名或密码有误"); } @Override public ResultVo phoneLogin(PhoneDto dto) { // 参数校验 if (dto.getPhone() == null ||!dto.getPhone().matches("1[3-9]\\d{9}")) { return ResultVo.error(400, "手机号格式错误"); } // 获取验证码 Integer code = (Integer) getVerificationCode(dto.getPhone()); if (code == null) { // logger.info("手机号 {} 验证码已过期", dto.getPhone()); return ResultVo.error(201, "验证码已过期"); } // 验证验证码 String codeStr = String.valueOf(code); String userCode = dto.getCode(); if (userCode == null ||!userCode.matches("\\d{6}")) { // logger.info("手机号 {} 输入的验证码格式错误", dto.getPhone()); return ResultVo.error(203, "验证码格式错误"); } if (!codeStr.equals(userCode)) { // logger.info("手机号 {} 验证码错误,Redis: {}, 用户输入: {}", // dto.getPhone(), codeStr, userCode); return ResultVo.error(202, "验证码错误"); } // 验证通过后删除验证码 deleteVerificationCode(dto.getPhone()); // 先判断账号是否存在 QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.lambda().eq(User::getPhone, dto.getPhone()); User user = userMapper.selectOne(queryWrapper); // if (user == null) { // user.setUsername("随机账户"+String.valueOf(IdUtil.getSnowflake().nextId())); // user.setId(IdUtil.getSnowflake().nextId()); // userMapper.insert(user); // redisClient.set("uid", user.getId()); // redisClient.expire("uid", 60*60); // Long id = user.getId(); // String token = AppJwtUtil.getToken(id); // redisClient.set("token", token); // Map map = new HashMap<>(); // map.put("token",token); // return ResultVo.success(map); // } // redisClient.set("uid", user.getId()); // redisClient.expire("uid", 60*60); String token = TokenUtils.createJwtToken(user.getId().toString()); // 使用用户ID作为键名的一部分 redisTemplate.opsForValue().set("userToken:" + user.getId(), token); redisTemplate.expire("userToken:" + user.getId(), 24, TimeUnit.HOURS); // 设置24小时过期 return ResultVo.success(token); } @Override public ResultVo forget(RegisterDto dto) { QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.eq("phone",dto.getPhone()); User user = userMapper.selectOne(queryWrapper); if (user==null){ return ResultVo.error("用户不存在"); } // 获取验证码 Object code = getVerificationCode(dto.getPhone()); if (code == null) { return ResultVo.error(201, "验证码已过期"); } String codeStr = String.valueOf(code); String userCode = dto.getCode(); if (!codeStr.equals(userCode)) { return ResultVo.error(202, "验证码错误"); } // 删除已使用的验证码 deleteVerificationCode(dto.getPhone()); //生成盐值 String uuid = UUID.randomUUID().toString().replaceAll("-", ""); user.setSalt(uuid); //获取密码 String password = dto.getPassword(); //加密 String md5Password = Md5Util.MD5(uuid + password); user.setPassword(md5Password); userMapper.updateById(user); return ResultVo.success("找回成功"); } @Override public ResultVo logout(String token) { if (token == null || token.isEmpty()) { return ResultVo.error("无效的token"); } try { // 解析token获取用户ID Long userId = TokenUtils.getUserId(token); if (userId == null) { return ResultVo.error("无效的token"); } // 从Redis删除token redisTemplate.delete("userToken:" + userId); // 可以设置token黑名单,防止已注销的token被再次使用 String blacklistKey = "token:blacklist:" + token; redisTemplate.opsForValue().set(blacklistKey, "1"); redisTemplate.expire(blacklistKey, 24, TimeUnit.HOURS); // 设置黑名单24小时过期 log.info("用户{}已成功退出登录", userId); return ResultVo.success("退出成功"); } catch (Exception e) { log.error("注销失败", e); return ResultVo.error("注销失败,请稍后再试"); } } @Override public ResultVo perfect(String token,PerfectDto dto) { Long userId = TokenUtils.getUserId(token); if (userId==null){ return ResultVo.error("用户不存在"); } User user = userMapper.selectById(userId); user.setUsername(dto.getUsername()); user.setEmail(dto.getEmail()); user.setAvatar(dto.getAvatar()); userMapper.updateById(user); return ResultVo.success("完善用户信息成功"); } }