UserLoginServiceImpl.java 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419
  1. package com.zhentao.user.service.impl;
  2. import cn.hutool.core.lang.Snowflake;
  3. import cn.hutool.core.util.IdUtil;
  4. import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
  5. import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
  6. import com.zhentao.enums.ApiServerException;
  7. import com.zhentao.exception.AsynException;
  8. import com.zhentao.information.service.WebSocketService;
  9. import com.zhentao.shouye.domain.UserShouye;
  10. import com.zhentao.shouye.mapper.UserShouyeMapper;
  11. import com.zhentao.tool.TokenUtils;
  12. import com.zhentao.user.domain.UserLogin;
  13. import com.zhentao.user.dto.*;
  14. import com.zhentao.user.service.EmailService;
  15. import com.zhentao.user.service.UserLoginService;
  16. import com.zhentao.user.mapper.UserLoginMapper;
  17. import com.zhentao.user.service.UserOnlineStatusService;
  18. import com.zhentao.userRelationships.domain.UserRelationships;
  19. import com.zhentao.userRelationships.mapper.UserRelationshipsMapper;
  20. import com.zhentao.utils.HttpUtils;
  21. import com.zhentao.utils.SnowflakeIdGenerator;
  22. import com.zhentao.vo.Result;
  23. import org.apache.http.HttpResponse;
  24. import org.redisson.api.RLock;
  25. import org.redisson.api.RedissonClient;
  26. import org.springframework.beans.factory.annotation.Autowired;
  27. import org.springframework.data.redis.core.StringRedisTemplate;
  28. import org.springframework.stereotype.Service;
  29. import org.springframework.util.DigestUtils;
  30. import org.springframework.util.StringUtils;
  31. import javax.servlet.http.HttpServletRequest;
  32. import java.nio.charset.StandardCharsets;
  33. import java.util.*;
  34. import java.util.concurrent.TimeUnit;
  35. /**
  36. * @author 86183
  37. * @description 针对表【user_login(用户)】的数据库操作Service实现
  38. * @createDate 2025-06-03 18:38:51
  39. */
  40. @Service
  41. public class UserLoginServiceImpl extends ServiceImpl<UserLoginMapper, UserLogin>
  42. implements UserLoginService{
  43. @Autowired
  44. private UserLoginMapper userLoginMapper;
  45. @Autowired
  46. private RedissonClient redissonClient;
  47. @Autowired
  48. private StringRedisTemplate stringRedisTemplate;
  49. @Autowired
  50. public WebSocketService webSocketService;
  51. @Autowired
  52. private EmailService emailService;
  53. @Autowired
  54. private UserOnlineStatusService onlineStatusService;
  55. @Autowired
  56. private UserShouyeMapper userShouyeMapper;
  57. @Autowired
  58. private UserRelationshipsMapper userRelationshipsMapper;
  59. //注册
  60. @Override
  61. public Result register(UserRegister userRegister) {
  62. // 对用户进行一个查询
  63. String username = userRegister.getUsername();
  64. QueryWrapper<UserLogin>queryWrapper=new QueryWrapper<>();
  65. queryWrapper.eq("user_username",username);
  66. UserLogin userLogin = userLoginMapper.selectOne(queryWrapper);
  67. // 若没有注册则进行一个注册功能
  68. if(userLogin==null){
  69. UserLogin user=new UserLogin();
  70. // 设置用户主键
  71. long l = IdUtil.getSnowflake(1, 1).nextId();
  72. user.setId(l);
  73. System.err.println("用户的ID:"+l);
  74. // 生成一个盐
  75. String salt=UUID.randomUUID().toString().replace("-","");
  76. // 进行一个md5加密
  77. String pwd=DigestUtils.md5DigestAsHex((salt+userRegister.getPassword()).getBytes(StandardCharsets.UTF_8));
  78. // 判断姓名非空
  79. if(StringUtils.isEmpty(userRegister.getNickname())){
  80. String uuid=UUID.randomUUID().toString().replace("-","");
  81. String nickName=uuid.substring(0,10);
  82. user.setNickName(nickName);
  83. }else {
  84. System.out.println(userRegister.getNickname());
  85. String nickName=userRegister.getNickname();
  86. System.out.println(nickName);
  87. user.setNickName(nickName);
  88. }
  89. user.setUserUsername(username);
  90. user.setUserPassword(pwd);
  91. user.setSalt(salt);
  92. if(userRegister.getType()==1){
  93. user.setUserMobile(userRegister.getMobile());
  94. System.err.println(user.getId());
  95. userLoginMapper.insert(user);
  96. String token = TokenUtils.generateToken(user.getId().toString());
  97. stringRedisTemplate.opsForValue().set(user.getId().toString(),token,10, TimeUnit.MINUTES);
  98. UserShouye userShouye = new UserShouye();
  99. userShouye.setId(IdUtil.getSnowflake().nextId());
  100. userShouye.setUid1(user.getId());
  101. userShouye.setUid2(1933707308387405824L);
  102. userShouye.setGid(0L);
  103. userShouye.setStatus(0);
  104. userShouyeMapper.insert(userShouye);
  105. UserRelationships userRelationships=new UserRelationships();
  106. userRelationships.setId(IdUtil.getSnowflake().nextId());
  107. userRelationships.setUserId(user.getId());
  108. userRelationships.setFriendId(1933707308387405824L);
  109. userRelationships.setStatus(1);
  110. userRelationships.setCreatedAt(new Date());
  111. userRelationships.setUpdatedAt(new Date());
  112. userRelationships.setIsBlacklist(0);
  113. userRelationships.setIsMoments(0);
  114. userRelationships.setIsDel(0);
  115. userRelationshipsMapper.insert(userRelationships);
  116. return Result.OK(null,"注册成功");
  117. }
  118. if(userRegister.getType()==2){
  119. user.setEmail(userRegister.getEmail());
  120. System.err.println(user.getId());
  121. userLoginMapper.insert(user);
  122. String token = TokenUtils.generateToken(user.getId().toString());
  123. stringRedisTemplate.opsForValue().set(user.getUserUsername(),token,10, TimeUnit.MINUTES);
  124. UserShouye userShouye = new UserShouye();
  125. userShouye.setId(IdUtil.getSnowflake().nextId());
  126. userShouye.setUid1(user.getId());
  127. userShouye.setUid2(1933707308387405824L);
  128. userShouye.setGid(0L);
  129. userShouye.setStatus(0);
  130. userShouyeMapper.insert(userShouye);
  131. UserRelationships userRelationships=new UserRelationships();
  132. userRelationships.setId(IdUtil.getSnowflake().nextId());
  133. userRelationships.setUserId(user.getId());
  134. userRelationships.setFriendId(1933707308387405824L);
  135. userRelationships.setStatus(1);
  136. userRelationships.setCreatedAt(new Date());
  137. userRelationships.setUpdatedAt(new Date());
  138. userRelationships.setIsBlacklist(0);
  139. userRelationships.setIsMoments(0);
  140. userRelationships.setIsDel(0);
  141. userRelationshipsMapper.insert(userRelationships);
  142. return Result.OK(null,"注册成功");
  143. }
  144. }
  145. return Result.ERR(null,"用户名已存在");
  146. }
  147. //验证码
  148. @Override
  149. public Result note(NoteDto noteDto) {
  150. String phone = noteDto.getPhone();
  151. QueryWrapper<UserLogin>queryWrapper=new QueryWrapper<>();
  152. queryWrapper.eq("user_mobile",phone);
  153. UserLogin userLogin = userLoginMapper.selectOne(queryWrapper);
  154. if(userLogin==null){
  155. //随机生成六位数
  156. int randomSixDigit=100000 + (int)(Math.random() * 900000);
  157. System.err.println("手机号:"+noteDto.getPhone());
  158. System.err.println("验证码:"+randomSixDigit);
  159. stringRedisTemplate.opsForValue().set(noteDto.getPhone(),randomSixDigit+"");
  160. String host = "https://gyytz.market.alicloudapi.com";
  161. String path = "/sms/smsSend";
  162. String method = "POST";
  163. String appcode = "b685e5e231ce404c855db67359acb1e1";
  164. Map<String, String> headers = new HashMap<String, String>();
  165. // 最后在 header 中的格式(中间是英文空格)为 Authorization:APPCODE 83359fd73fe94948385f570e3c139105
  166. headers.put("Authorization", "APPCODE " + appcode);
  167. Map<String, String> querys = new HashMap<String, String>();
  168. System.out.println(noteDto.getPhone());
  169. querys.put("mobile",noteDto.getPhone());
  170. querys.put("param", "**code**:"+randomSixDigit+",**minute**:5");
  171. // smsSignId(短信前缀)和 templateId(短信模板),可登录国阳云控制台自助申请。参考文档:http://help.guoyangyun.com/Problem/Qm.html
  172. querys.put("smsSignId", "2e65b1bb3d054466b82f0c9d125465e2");
  173. querys.put("templateId", "908e94ccf08b4476ba6c876d13f084ad");
  174. Map<String, String> bodys = new HashMap<String, String>();
  175. try {
  176. /**
  177. * 重要提示如下:
  178. * HttpUtils 请从
  179. * https://github.com/aliyun/api-gateway-demo-sign-java/blob/master/src/main/java/com/aliyun/api/gateway/demo/util/HttpUtils.java
  180. * 下载
  181. *
  182. * 相应的依赖请参照
  183. * https://github.com/aliyun/api-gateway-demo-sign-java/blob/master/pom.xml
  184. */
  185. HttpResponse response = HttpUtils.doPost(host, path, method, headers, querys, bodys);
  186. System.out.println(response.toString());
  187. // 获取 response 的 body
  188. // System.out.println(EntityUtils.toString(response.getEntity()));
  189. } catch (Exception e) {
  190. e.printStackTrace();
  191. }
  192. return Result.OK(null,"发送成功");
  193. }else {
  194. return Result.ERR(null,"手机号已存在");
  195. }
  196. }
  197. //登录
  198. /**
  199. * 用户登录方法
  200. * 使用Redis分布式锁来防止并发登录
  201. * @param userLoginDto 用户登录信息,包含手机号和验证码
  202. * @return 登录结果,包括token和提示信息
  203. */
  204. //账号密码登录
  205. /**
  206. * 使用用户名和密码进行用户登录的方法
  207. * 该方法实现了用户认证和JWT令牌的生成
  208. *
  209. * @param userPassDto 包含用户名和密码的DTO对象
  210. * @return 登录结果,包括登录状态和JWT令牌
  211. */
  212. @Override
  213. public Result UserPassLogin(UserPassDto userPassDto) {
  214. System.err.println(userPassDto);
  215. // 获取Redisson客户端的锁对象,用于处理并发登录请求
  216. RLock lock = redissonClient.getLock("user"+userPassDto.getUsername());
  217. try {
  218. // 尝试获取锁,设置等待和持有时间
  219. boolean b = lock.tryLock(10, 20, TimeUnit.SECONDS);
  220. if (b){
  221. // 查询用户信息,根据用户名
  222. QueryWrapper<UserLogin> queryWrapper = new QueryWrapper<>();
  223. queryWrapper.eq("user_username",userPassDto.getUsername())
  224. .or()
  225. .eq("user_mobile",userPassDto.getUsername())
  226. .or()
  227. .eq("email",userPassDto.getUsername());
  228. UserLogin one = this.getOne(queryWrapper);
  229. // 如果用户不存在,抛出异常
  230. if (one==null){
  231. throw new AsynException(ApiServerException.NULL_USERNAME);
  232. }
  233. // 获取用户盐值,用于密码加密
  234. String salt = one.getSalt();
  235. // 加密用户输入的密码,并与数据库中的密码进行比较
  236. String s = DigestUtils.md5DigestAsHex((salt + userPassDto.getPassword()).getBytes());
  237. if (!s.equals(one.getUserPassword())){
  238. throw new AsynException(ApiServerException.NULL_PASSWORD);
  239. }
  240. // 生成JWT令牌
  241. String jwtToken = TokenUtils.generateToken(one.getId()+"");
  242. stringRedisTemplate.opsForValue().set(one.getId().toString(),jwtToken);
  243. System.err.println(stringRedisTemplate.opsForValue().get(one.getId().toString()));
  244. // 返回登录成功结果和JWT令牌
  245. // 将用户ID和token存储到WebSocketService中
  246. webSocketService.storeUserToken(one.getId()+"", jwtToken);
  247. Map<String,Object> map = new HashMap<>();
  248. map.put("token",jwtToken);
  249. map.put("userId",one.getId()+"");
  250. map.put("image",one.getAvatar());
  251. //用户上线
  252. onlineStatusService.userGoOnline(one.getId());
  253. return Result.OK(map,"登录成功");
  254. }else {
  255. // 如果获取锁超时,返回错误信息
  256. return Result.ERR("获取锁超时",null);
  257. }
  258. }catch (InterruptedException e){
  259. // 如果线程被中断,恢复中断状态,并返回错误信息
  260. System.err.println("锁异常");
  261. Thread.currentThread().interrupt();
  262. return Result.ERR("线程被中断",null);
  263. }finally {
  264. // 释放锁
  265. lock.unlock();
  266. }
  267. }
  268. //忘记密码
  269. @Override
  270. public Result ForgetPass(ForgetPassDto forgetPassDto) {
  271. RLock lock = redissonClient.getLock(forgetPassDto.getPhone() + "Phone");
  272. try {
  273. boolean b = lock.tryLock(10, 20, TimeUnit.SECONDS);
  274. if (b) {
  275. QueryWrapper<UserLogin> queryWrapper = new QueryWrapper<>();
  276. queryWrapper.eq("user_mobile", forgetPassDto.getPhone());
  277. UserLogin one = this.getOne(queryWrapper);
  278. if (one == null) {
  279. return Result.ERR("用户不存在", null);
  280. }
  281. // 获取Redis中的验证码
  282. String s = stringRedisTemplate.opsForValue().get(forgetPassDto.getPhone());
  283. // 验证码不匹配则抛出异常
  284. if (!s.equals(forgetPassDto.getCode())) {
  285. throw new AsynException(ApiServerException.NOTE_ERROR);
  286. }
  287. // 获取用户信息,根据手机号
  288. String salt = one.getSalt();
  289. String s1 = DigestUtils.md5DigestAsHex((salt + forgetPassDto.getPassword()).getBytes());
  290. one.setUserPassword(s1);
  291. boolean b1 = this.updateById(one);
  292. if (b1){
  293. return Result.OK("修改成功", null);
  294. }else {
  295. return Result.ERR("修改失败", null);
  296. }
  297. }
  298. } catch (InterruptedException e) {
  299. throw new RuntimeException(e);
  300. }
  301. return null;
  302. }
  303. //获取用户信息
  304. @Override
  305. public UserLogin getUserById(Long id) {
  306. UserLogin userLogin = userLoginMapper.selectById(id);
  307. return userLogin;
  308. }
  309. @Override
  310. public List<UserLogin> searchFriends(String keyword) {
  311. if(!StringUtils.hasLength(keyword))
  312. return null;
  313. //根据昵称、账号进行模糊查询
  314. List<UserLogin> list=this.query()
  315. .like("user_username",keyword)
  316. .or()
  317. .like("nick_name",keyword)
  318. .list();
  319. return list;
  320. }
  321. @Override
  322. public Optional<UserLogin> findById(Long userId) {
  323. return Optional.ofNullable(userLoginMapper.selectById(userId));
  324. }
  325. @Override
  326. public Result logout(HttpServletRequest request) {
  327. String token = request.getHeader("token");
  328. String userId =TokenUtils.getUserIdFromToken(token);
  329. Long id = Long.parseLong(userId);
  330. onlineStatusService.userGoOffline(id);
  331. return Result.OK(null,"退出成功");
  332. }
  333. @Override
  334. public Result emailRegister(EmailDto emailDto) {
  335. UserLogin userLogin = new UserLogin();
  336. QueryWrapper<UserLogin> queryWrapper = new QueryWrapper<>();
  337. queryWrapper.eq("email", emailDto.getEmail());
  338. UserLogin user = userLoginMapper.selectOne(queryWrapper);
  339. if (user == null) {
  340. userLogin.setId(SnowflakeIdGenerator.getSnowId());
  341. emailService.sendVerificationEmail(emailDto.getEmail());
  342. return Result.OK(null,"邮箱发送成功,请前往邮箱注册");
  343. } else {
  344. throw new AsynException(ApiServerException.EMAIL_EXIST);
  345. }
  346. }
  347. @Override
  348. public Result validateCode(NoteDto noteDto) {
  349. String s = stringRedisTemplate.opsForValue().get(noteDto.getPhone());
  350. System.err.println(s);
  351. if(noteDto.getCode().equals(s)){
  352. return Result.OK(null,"验证成功");
  353. }
  354. return Result.ERR(null,"验证码错误");
  355. }
  356. @Override
  357. public Result validateEmailCode(EmailDto emailDto) {
  358. String s = stringRedisTemplate.opsForValue().get(emailDto.getEmail());
  359. System.err.println(s);
  360. if(emailDto.getCode().equals(s)){
  361. return Result.OK(null,"验证成功");
  362. }
  363. return Result.ERR(null,"验证码错误");
  364. }
  365. @Override
  366. public Result updateUserInfo(Userinfox userinfox) {
  367. UserLogin one = this.getOne(new QueryWrapper<UserLogin>().eq("id", userinfox.getId()));
  368. one.setNickName(userinfox.getNickName());
  369. one.setGender(userinfox.getGender());
  370. one.setUserIntro(userinfox.getUserIntro());
  371. one.setAvatar(userinfox.getAvatar());
  372. boolean b = this.updateById(one);
  373. if(b){
  374. return Result.OK("修改成功",null);
  375. }else {
  376. return Result.ERR("修改失败", null);
  377. }
  378. }
  379. }