package com.zhentao.user.service.impl; import cn.hutool.core.lang.Snowflake; import cn.hutool.core.util.IdUtil; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.zhentao.enums.ApiServerException; import com.zhentao.exception.AsynException; import com.zhentao.information.service.WebSocketService; import com.zhentao.shouye.domain.UserShouye; import com.zhentao.shouye.mapper.UserShouyeMapper; import com.zhentao.tool.TokenUtils; import com.zhentao.user.domain.UserLogin; import com.zhentao.user.dto.*; import com.zhentao.user.service.EmailService; import com.zhentao.user.service.UserLoginService; import com.zhentao.user.mapper.UserLoginMapper; import com.zhentao.user.service.UserOnlineStatusService; import com.zhentao.userRelationships.domain.UserRelationships; import com.zhentao.userRelationships.mapper.UserRelationshipsMapper; import com.zhentao.utils.HttpUtils; import com.zhentao.utils.SnowflakeIdGenerator; import com.zhentao.vo.Result; import org.apache.http.HttpResponse; import org.redisson.api.RLock; import org.redisson.api.RedissonClient; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Service; import org.springframework.util.DigestUtils; import org.springframework.util.StringUtils; import javax.servlet.http.HttpServletRequest; import java.nio.charset.StandardCharsets; import java.util.*; import java.util.concurrent.TimeUnit; /** * @author 86183 * @description 针对表【user_login(用户)】的数据库操作Service实现 * @createDate 2025-06-03 18:38:51 */ @Service public class UserLoginServiceImpl extends ServiceImpl implements UserLoginService{ @Autowired private UserLoginMapper userLoginMapper; @Autowired private RedissonClient redissonClient; @Autowired private StringRedisTemplate stringRedisTemplate; @Autowired public WebSocketService webSocketService; @Autowired private EmailService emailService; @Autowired private UserOnlineStatusService onlineStatusService; @Autowired private UserShouyeMapper userShouyeMapper; @Autowired private UserRelationshipsMapper userRelationshipsMapper; //注册 @Override public Result register(UserRegister userRegister) { // 对用户进行一个查询 String username = userRegister.getUsername(); QueryWrapperqueryWrapper=new QueryWrapper<>(); queryWrapper.eq("user_username",username); UserLogin userLogin = userLoginMapper.selectOne(queryWrapper); // 若没有注册则进行一个注册功能 if(userLogin==null){ UserLogin user=new UserLogin(); // 设置用户主键 long l = IdUtil.getSnowflake(1, 1).nextId(); user.setId(l); System.err.println("用户的ID:"+l); // 生成一个盐 String salt=UUID.randomUUID().toString().replace("-",""); // 进行一个md5加密 String pwd=DigestUtils.md5DigestAsHex((salt+userRegister.getPassword()).getBytes(StandardCharsets.UTF_8)); // 判断姓名非空 if(StringUtils.isEmpty(userRegister.getNickname())){ String uuid=UUID.randomUUID().toString().replace("-",""); String nickName=uuid.substring(0,10); user.setNickName(nickName); }else { System.out.println(userRegister.getNickname()); String nickName=userRegister.getNickname(); System.out.println(nickName); user.setNickName(nickName); } user.setUserUsername(username); user.setUserPassword(pwd); user.setSalt(salt); if(userRegister.getType()==1){ user.setUserMobile(userRegister.getMobile()); System.err.println(user.getId()); userLoginMapper.insert(user); String token = TokenUtils.generateToken(user.getId().toString()); stringRedisTemplate.opsForValue().set(user.getId().toString(),token,10, TimeUnit.MINUTES); UserShouye userShouye = new UserShouye(); userShouye.setId(IdUtil.getSnowflake().nextId()); userShouye.setUid1(user.getId()); userShouye.setUid2(1933707308387405824L); userShouye.setGid(0L); userShouye.setStatus(0); userShouyeMapper.insert(userShouye); UserRelationships userRelationships=new UserRelationships(); userRelationships.setId(IdUtil.getSnowflake().nextId()); userRelationships.setUserId(user.getId()); userRelationships.setFriendId(1933707308387405824L); userRelationships.setStatus(1); userRelationships.setCreatedAt(new Date()); userRelationships.setUpdatedAt(new Date()); userRelationships.setIsBlacklist(0); userRelationships.setIsMoments(0); userRelationships.setIsDel(0); userRelationshipsMapper.insert(userRelationships); return Result.OK(null,"注册成功"); } if(userRegister.getType()==2){ user.setEmail(userRegister.getEmail()); System.err.println(user.getId()); userLoginMapper.insert(user); String token = TokenUtils.generateToken(user.getId().toString()); stringRedisTemplate.opsForValue().set(user.getUserUsername(),token,10, TimeUnit.MINUTES); UserShouye userShouye = new UserShouye(); userShouye.setId(IdUtil.getSnowflake().nextId()); userShouye.setUid1(user.getId()); userShouye.setUid2(1933707308387405824L); userShouye.setGid(0L); userShouye.setStatus(0); userShouyeMapper.insert(userShouye); UserRelationships userRelationships=new UserRelationships(); userRelationships.setId(IdUtil.getSnowflake().nextId()); userRelationships.setUserId(user.getId()); userRelationships.setFriendId(1933707308387405824L); userRelationships.setStatus(1); userRelationships.setCreatedAt(new Date()); userRelationships.setUpdatedAt(new Date()); userRelationships.setIsBlacklist(0); userRelationships.setIsMoments(0); userRelationships.setIsDel(0); userRelationshipsMapper.insert(userRelationships); return Result.OK(null,"注册成功"); } } return Result.ERR(null,"用户名已存在"); } //验证码 @Override public Result note(NoteDto noteDto) { String phone = noteDto.getPhone(); QueryWrapperqueryWrapper=new QueryWrapper<>(); queryWrapper.eq("user_mobile",phone); UserLogin userLogin = userLoginMapper.selectOne(queryWrapper); if(userLogin==null){ //随机生成六位数 int randomSixDigit=100000 + (int)(Math.random() * 900000); System.err.println("手机号:"+noteDto.getPhone()); System.err.println("验证码:"+randomSixDigit); stringRedisTemplate.opsForValue().set(noteDto.getPhone(),randomSixDigit+""); String host = "https://gyytz.market.alicloudapi.com"; String path = "/sms/smsSend"; String method = "POST"; String appcode = "b685e5e231ce404c855db67359acb1e1"; Map headers = new HashMap(); // 最后在 header 中的格式(中间是英文空格)为 Authorization:APPCODE 83359fd73fe94948385f570e3c139105 headers.put("Authorization", "APPCODE " + appcode); Map querys = new HashMap(); System.out.println(noteDto.getPhone()); querys.put("mobile",noteDto.getPhone()); querys.put("param", "**code**:"+randomSixDigit+",**minute**:5"); // smsSignId(短信前缀)和 templateId(短信模板),可登录国阳云控制台自助申请。参考文档:http://help.guoyangyun.com/Problem/Qm.html querys.put("smsSignId", "2e65b1bb3d054466b82f0c9d125465e2"); querys.put("templateId", "908e94ccf08b4476ba6c876d13f084ad"); Map bodys = new HashMap(); try { /** * 重要提示如下: * HttpUtils 请从 * https://github.com/aliyun/api-gateway-demo-sign-java/blob/master/src/main/java/com/aliyun/api/gateway/demo/util/HttpUtils.java * 下载 * * 相应的依赖请参照 * https://github.com/aliyun/api-gateway-demo-sign-java/blob/master/pom.xml */ HttpResponse response = HttpUtils.doPost(host, path, method, headers, querys, bodys); System.out.println(response.toString()); // 获取 response 的 body // System.out.println(EntityUtils.toString(response.getEntity())); } catch (Exception e) { e.printStackTrace(); } return Result.OK(null,"发送成功"); }else { return Result.ERR(null,"手机号已存在"); } } //登录 /** * 用户登录方法 * 使用Redis分布式锁来防止并发登录 * @param userLoginDto 用户登录信息,包含手机号和验证码 * @return 登录结果,包括token和提示信息 */ //账号密码登录 /** * 使用用户名和密码进行用户登录的方法 * 该方法实现了用户认证和JWT令牌的生成 * * @param userPassDto 包含用户名和密码的DTO对象 * @return 登录结果,包括登录状态和JWT令牌 */ @Override public Result UserPassLogin(UserPassDto userPassDto) { System.err.println(userPassDto); // 获取Redisson客户端的锁对象,用于处理并发登录请求 RLock lock = redissonClient.getLock("user"+userPassDto.getUsername()); try { // 尝试获取锁,设置等待和持有时间 boolean b = lock.tryLock(10, 20, TimeUnit.SECONDS); if (b){ // 查询用户信息,根据用户名 QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.eq("user_username",userPassDto.getUsername()) .or() .eq("user_mobile",userPassDto.getUsername()) .or() .eq("email",userPassDto.getUsername()); UserLogin one = this.getOne(queryWrapper); // 如果用户不存在,抛出异常 if (one==null){ throw new AsynException(ApiServerException.NULL_USERNAME); } // 获取用户盐值,用于密码加密 String salt = one.getSalt(); // 加密用户输入的密码,并与数据库中的密码进行比较 String s = DigestUtils.md5DigestAsHex((salt + userPassDto.getPassword()).getBytes()); if (!s.equals(one.getUserPassword())){ throw new AsynException(ApiServerException.NULL_PASSWORD); } // 生成JWT令牌 String jwtToken = TokenUtils.generateToken(one.getId()+""); stringRedisTemplate.opsForValue().set(one.getId().toString(),jwtToken); System.err.println(stringRedisTemplate.opsForValue().get(one.getId().toString())); // 返回登录成功结果和JWT令牌 // 将用户ID和token存储到WebSocketService中 webSocketService.storeUserToken(one.getId()+"", jwtToken); Map map = new HashMap<>(); map.put("token",jwtToken); map.put("userId",one.getId()+""); map.put("image",one.getAvatar()); //用户上线 onlineStatusService.userGoOnline(one.getId()); return Result.OK(map,"登录成功"); }else { // 如果获取锁超时,返回错误信息 return Result.ERR("获取锁超时",null); } }catch (InterruptedException e){ // 如果线程被中断,恢复中断状态,并返回错误信息 System.err.println("锁异常"); Thread.currentThread().interrupt(); return Result.ERR("线程被中断",null); }finally { // 释放锁 lock.unlock(); } } //忘记密码 @Override public Result ForgetPass(ForgetPassDto forgetPassDto) { RLock lock = redissonClient.getLock(forgetPassDto.getPhone() + "Phone"); try { boolean b = lock.tryLock(10, 20, TimeUnit.SECONDS); if (b) { QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.eq("user_mobile", forgetPassDto.getPhone()); UserLogin one = this.getOne(queryWrapper); if (one == null) { return Result.ERR("用户不存在", null); } // 获取Redis中的验证码 String s = stringRedisTemplate.opsForValue().get(forgetPassDto.getPhone()); // 验证码不匹配则抛出异常 if (!s.equals(forgetPassDto.getCode())) { throw new AsynException(ApiServerException.NOTE_ERROR); } // 获取用户信息,根据手机号 String salt = one.getSalt(); String s1 = DigestUtils.md5DigestAsHex((salt + forgetPassDto.getPassword()).getBytes()); one.setUserPassword(s1); boolean b1 = this.updateById(one); if (b1){ return Result.OK("修改成功", null); }else { return Result.ERR("修改失败", null); } } } catch (InterruptedException e) { throw new RuntimeException(e); } return null; } //获取用户信息 @Override public UserLogin getUserById(Long id) { UserLogin userLogin = userLoginMapper.selectById(id); return userLogin; } @Override public List searchFriends(String keyword) { if(!StringUtils.hasLength(keyword)) return null; //根据昵称、账号进行模糊查询 List list=this.query() .like("user_username",keyword) .or() .like("nick_name",keyword) .list(); return list; } @Override public Optional findById(Long userId) { return Optional.ofNullable(userLoginMapper.selectById(userId)); } @Override public Result logout(HttpServletRequest request) { String token = request.getHeader("token"); String userId =TokenUtils.getUserIdFromToken(token); Long id = Long.parseLong(userId); onlineStatusService.userGoOffline(id); return Result.OK(null,"退出成功"); } @Override public Result emailRegister(EmailDto emailDto) { UserLogin userLogin = new UserLogin(); QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.eq("email", emailDto.getEmail()); UserLogin user = userLoginMapper.selectOne(queryWrapper); if (user == null) { userLogin.setId(SnowflakeIdGenerator.getSnowId()); emailService.sendVerificationEmail(emailDto.getEmail()); return Result.OK(null,"邮箱发送成功,请前往邮箱注册"); } else { throw new AsynException(ApiServerException.EMAIL_EXIST); } } @Override public Result validateCode(NoteDto noteDto) { String s = stringRedisTemplate.opsForValue().get(noteDto.getPhone()); System.err.println(s); if(noteDto.getCode().equals(s)){ return Result.OK(null,"验证成功"); } return Result.ERR(null,"验证码错误"); } @Override public Result validateEmailCode(EmailDto emailDto) { String s = stringRedisTemplate.opsForValue().get(emailDto.getEmail()); System.err.println(s); if(emailDto.getCode().equals(s)){ return Result.OK(null,"验证成功"); } return Result.ERR(null,"验证码错误"); } @Override public Result updateUserInfo(Userinfox userinfox) { UserLogin one = this.getOne(new QueryWrapper().eq("id", userinfox.getId())); one.setNickName(userinfox.getNickName()); one.setGender(userinfox.getGender()); one.setUserIntro(userinfox.getUserIntro()); one.setAvatar(userinfox.getAvatar()); boolean b = this.updateById(one); if(b){ return Result.OK("修改成功",null); }else { return Result.ERR("修改失败", null); } } }