Răsfoiți Sursa

update 用户中心密码操作修改逻辑

宋天 3 ani în urmă
părinte
comite
21fbe91e39

+ 7 - 7
yudao-admin-server/src/main/resources/application-local.yaml

@@ -44,16 +44,16 @@ spring:
       datasource:
         master:
           name: ruoyi-vue-pro
-          url: jdbc:mysql://127.0.0.1:3306/${spring.datasource.dynamic.datasource.master.name}?useSSL=false&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT
-          driver-class-name: com.mysql.jdbc.Driver
-          username: root
-          password: 123456
-        slave: # 模拟从库,可根据自己需要修改
-          name: ruoyi-vue-pro
-          url: jdbc:mysql://127.0.0.1:3306/${spring.datasource.dynamic.datasource.slave.name}?useSSL=false&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT
+          url: jdbc:mysql://127.0.0.1:3306/ruoyi-vue-pro?useSSL=false&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT
           driver-class-name: com.mysql.jdbc.Driver
           username: root
           password: 123456
+#        slave: # 模拟从库,可根据自己需要修改
+#          name: ruoyi-vue-pro
+#          url: jdbc:mysql://127.0.0.1:3306/${spring.datasource.dynamic.datasource.slave.name}?useSSL=false&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT
+#          driver-class-name: com.mysql.jdbc.Driver
+#          username: root
+#          password: 123456
 
 
   activiti:

+ 11 - 16
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/member/service/user/impl/MbrUserServiceImpl.java

@@ -4,20 +4,20 @@ import cn.hutool.core.io.IoUtil;
 import cn.hutool.core.util.IdUtil;
 import cn.iocoder.yudao.coreservice.modules.infra.service.file.InfFileCoreService;
 import cn.iocoder.yudao.coreservice.modules.member.dal.dataobject.user.MbrUserDO;
-import cn.iocoder.yudao.userserver.modules.member.controller.user.vo.MbrUserInfoRespVO;
 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
+import cn.iocoder.yudao.userserver.modules.member.controller.user.vo.MbrUserInfoRespVO;
 import cn.iocoder.yudao.userserver.modules.member.controller.user.vo.MbrUserUpdateMobileReqVO;
 import cn.iocoder.yudao.userserver.modules.member.convert.user.UserProfileConvert;
 import cn.iocoder.yudao.userserver.modules.member.dal.mysql.user.MbrUserMapper;
 import cn.iocoder.yudao.userserver.modules.member.service.user.MbrUserService;
 import cn.iocoder.yudao.userserver.modules.system.dal.dataobject.sms.SysSmsCodeDO;
 import cn.iocoder.yudao.userserver.modules.system.enums.sms.SysSmsSceneEnum;
-import cn.iocoder.yudao.userserver.modules.system.service.auth.SysAuthService;
 import cn.iocoder.yudao.userserver.modules.system.service.sms.SysSmsCodeService;
 import com.google.common.annotations.VisibleForTesting;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.security.crypto.password.PasswordEncoder;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
 
 import javax.annotation.Resource;
 import javax.validation.Valid;
@@ -28,7 +28,6 @@ import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionU
 import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP;
 import static cn.iocoder.yudao.userserver.modules.member.enums.MbrErrorCodeConstants.USER_NOT_EXISTS;
 import static cn.iocoder.yudao.userserver.modules.system.enums.SysErrorCodeConstants.USER_SMS_CODE_IS_UNUSED;
-import static cn.iocoder.yudao.userserver.modules.system.enums.SysErrorCodeConstants.USER_SMS_CODE_NOT_CORRECT;
 
 /**
  * User Service 实现类
@@ -49,9 +48,6 @@ public class MbrUserServiceImpl implements MbrUserService {
     @Resource
     private PasswordEncoder passwordEncoder;
 
-    @Resource
-    private SysAuthService sysAuthService;
-
     @Resource
     private SysSmsCodeService smsCodeService;
 
@@ -130,24 +126,23 @@ public class MbrUserServiceImpl implements MbrUserService {
     }
 
     @Override
+    @Transactional(rollbackFor = Exception.class)
     public void updateMobile(Long userId, MbrUserUpdateMobileReqVO reqVO) {
         // 检测用户是否存在
         checkUserExists(userId);
-        // 校验验证码,并标记为已使用
-        smsCodeService.useSmsCode(reqVO.getMobile(), SysSmsSceneEnum.CHANGE_MOBILE_BY_SMS.getScene(), reqVO.getCode(),getClientIP());
-
-        // 检测新手机和旧手机的验证码是否在30分钟内
-        SysSmsCodeDO smsOldCodeDO = smsCodeService.checkCodeIsExpired(reqVO.getOldMobile(), reqVO.getOldCode(), SysSmsSceneEnum.CHANGE_MOBILE_BY_SMS.getScene());
-        SysSmsCodeDO smsNewCodeDO = smsCodeService.checkCodeIsExpired(reqVO.getMobile(), reqVO.getCode(), SysSmsSceneEnum.CHANGE_MOBILE_BY_SMS.getScene());
 
-        // 判断新旧code是否未被使用,如果是,抛出异常
-        if (Boolean.FALSE.equals(smsOldCodeDO.getUsed()) || Boolean.FALSE.equals(smsNewCodeDO.getUsed())){
+        // 校验旧手机和旧验证码
+        SysSmsCodeDO sysSmsCodeDO = smsCodeService.checkCodeIsExpired(reqVO.getOldMobile(), reqVO.getOldCode(), SysSmsSceneEnum.CHANGE_MOBILE_BY_SMS.getScene());
+        // 判断旧code是否未被使用,如果是,抛出异常
+        if (Boolean.FALSE.equals(sysSmsCodeDO.getUsed())){
             throw exception(USER_SMS_CODE_IS_UNUSED);
         }
 
+        // 使用新验证码
+        smsCodeService.useSmsCode(reqVO.getMobile(), SysSmsSceneEnum.CHANGE_MOBILE_BY_SMS.getScene(), reqVO.getCode(),getClientIP());
+
         // 更新用户手机
-        MbrUserDO userDO = MbrUserDO.builder().build();
-        userDO.setMobile(reqVO.getMobile());
+        MbrUserDO userDO = MbrUserDO.builder().id(userId).mobile(reqVO.getMobile()).build();
         userMapper.updateById(userDO);
     }
 

+ 1 - 1
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/enums/SysErrorCodeConstants.java

@@ -24,7 +24,7 @@ public interface SysErrorCodeConstants {
     ErrorCode USER_SMS_CODE_EXCEED_SEND_MAXIMUM_QUANTITY_PER_DAY = new ErrorCode(1005001004, "超过每日短信发送数量");
     ErrorCode USER_SMS_CODE_SEND_TOO_FAST = new ErrorCode(1005001005, "短信发送过于频率");
     ErrorCode USER_SMS_CODE_IS_EXISTS = new ErrorCode(1005001006, "手机号已被使用");
-    ErrorCode USER_SMS_CODE_IS_UNUSED = new ErrorCode(1005001006, "手机号未被使用");
+    ErrorCode USER_SMS_CODE_IS_UNUSED = new ErrorCode(1005001006, "验证码未被使用");
 
     // ========== 用户模块 1005002000 ==========
     ErrorCode USER_NOT_EXISTS = new ErrorCode(1005002001, "用户不存在");

+ 11 - 11
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/service/sms/SysSmsCodeService.java

@@ -2,9 +2,7 @@ package cn.iocoder.yudao.userserver.modules.system.service.sms;
 
 import cn.iocoder.yudao.framework.common.exception.ServiceException;
 import cn.iocoder.yudao.framework.common.validation.Mobile;
-import cn.iocoder.yudao.userserver.modules.system.controller.auth.vo.SysAuthCheckCodeReqVO;
 import cn.iocoder.yudao.userserver.modules.system.controller.auth.vo.SysAuthSendSmsReqVO;
-import cn.iocoder.yudao.userserver.modules.system.controller.auth.vo.SysAuthSmsLoginReqVO;
 import cn.iocoder.yudao.userserver.modules.system.dal.dataobject.sms.SysSmsCodeDO;
 import cn.iocoder.yudao.userserver.modules.system.enums.sms.SysSmsSceneEnum;
 
@@ -18,14 +16,15 @@ public interface SysSmsCodeService {
     /**
      * 创建短信验证码,并进行发送
      *
-     * @param mobile 手机号
-     * @param scene 发送场景 {@link SysSmsSceneEnum}
+     * @param mobile   手机号
+     * @param scene    发送场景 {@link SysSmsSceneEnum}
      * @param createIp 发送 IP
      */
     void sendSmsCode(@Mobile String mobile, Integer scene, String createIp);
 
     /**
      * 发送短信验证码,并检测手机号是否已被注册
+     *
      * @param reqVO 请求实体
      */
     void sendSmsNewCode(SysAuthSendSmsReqVO reqVO);
@@ -36,25 +35,26 @@ public interface SysSmsCodeService {
      * 如果错误,则抛出 {@link ServiceException} 异常
      *
      * @param mobile 手机号
-     * @param scene 发送场景
-     * @param code 验证码
+     * @param scene  发送场景
+     * @param code   验证码
      * @param usedIp 使用 IP
      */
     void useSmsCode(@Mobile String mobile, Integer scene, String code, String usedIp);
 
     /**
      * 根据用户id发送验证码
+     *
      * @param userId 用户id
      */
     void sendSmsCodeLogin(Long userId);
 
+
     /**
-     * 检测手机验证码是否有效
-     * @param mobile 手机
+     * 检验证码是否有效
+     * @param mobile 手机
      * @param code 验证码
-     * @param scene 发送场景 {@link SysSmsSceneEnum}
-     * @return SysSmsCodeDO 手机验证码
+     * @param scene 使用场景
+     * @return 验证码记录
      */
     SysSmsCodeDO checkCodeIsExpired(String mobile, String code, Integer scene);
-
 }

+ 14 - 21
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/service/sms/impl/SysSmsCodeServiceImpl.java

@@ -4,7 +4,6 @@ import cn.hutool.core.map.MapUtil;
 import cn.iocoder.yudao.coreservice.modules.member.dal.dataobject.user.MbrUserDO;
 import cn.iocoder.yudao.coreservice.modules.system.service.sms.SysSmsCoreService;
 import cn.iocoder.yudao.userserver.modules.member.service.user.MbrUserService;
-import cn.iocoder.yudao.userserver.modules.system.controller.auth.vo.SysAuthCheckCodeReqVO;
 import cn.iocoder.yudao.userserver.modules.system.controller.auth.vo.SysAuthSendSmsReqVO;
 import cn.iocoder.yudao.userserver.modules.system.dal.dataobject.sms.SysSmsCodeDO;
 import cn.iocoder.yudao.userserver.modules.system.dal.mysql.sms.SysSmsCodeMapper;
@@ -92,21 +91,14 @@ public class SysSmsCodeServiceImpl implements SysSmsCodeService {
 
     @Override
     public void useSmsCode(String mobile, Integer scene, String code, String usedIp) {
-        // 校验验证码
-        SysSmsCodeDO lastSmsCode = smsCodeMapper.selectLastByMobile(mobile, null,scene);
-        if (lastSmsCode == null) { // 若验证码不存在,抛出异常
-            throw exception(USER_SMS_CODE_NOT_FOUND);
-        }
-        if (System.currentTimeMillis() - lastSmsCode.getCreateTime().getTime()
-                >= smsCodeProperties.getExpireTimes().toMillis()) { // 验证码已过期
-            throw exception(USER_SMS_CODE_EXPIRED);
-        }
-        if (lastSmsCode.getUsed()) { // 验证码已使用
+
+        // 检测验证码是否有效
+        SysSmsCodeDO lastSmsCode = this.checkCodeIsExpired(mobile, code, scene);
+
+        // 判断验证码是否已被使用
+        if (Boolean.TRUE.equals(lastSmsCode.getUsed())) {
             throw exception(USER_SMS_CODE_USED);
         }
-        if (!lastSmsCode.getCode().equals(code)) {
-            throw exception(USER_SMS_CODE_NOT_CORRECT);
-        }
 
         // 使用验证码
         smsCodeMapper.updateById(SysSmsCodeDO.builder().id(lastSmsCode.getId())
@@ -125,19 +117,20 @@ public class SysSmsCodeServiceImpl implements SysSmsCodeService {
 
     @Override
     public SysSmsCodeDO checkCodeIsExpired(String mobile, String code, Integer scene) {
-        SysSmsCodeDO lastSmsCode = smsCodeMapper.selectLastByMobile(mobile, code, scene);
+        // 校验验证码
+        SysSmsCodeDO lastSmsCode = smsCodeMapper.selectLastByMobile(mobile,code,scene);
 
-        // 检测验证码是否存在
-        if (lastSmsCode == null){
-            throw exception(USER_SMS_CODE_EXPIRED);
+        // 若验证码不存在,抛出异常
+        if (lastSmsCode == null) {
+            throw exception(USER_SMS_CODE_NOT_FOUND);
         }
-
-        // 检测验证码是否过期
         if (System.currentTimeMillis() - lastSmsCode.getCreateTime().getTime()
-                >= smsCodeProperties.getExpireTimes().toMillis()) {
+                >= smsCodeProperties.getExpireTimes().toMillis()) { // 验证码已过期
             throw exception(USER_SMS_CODE_EXPIRED);
         }
+
         return lastSmsCode;
+
     }
 
 }

+ 15 - 13
yudao-user-server/src/test/java/cn/iocoder/yudao/userserver/modules/member/service/MbrUserServiceImplTest.java

@@ -1,5 +1,6 @@
 package cn.iocoder.yudao.userserver.modules.member.service;
 
+import cn.hutool.core.util.RandomUtil;
 import cn.iocoder.yudao.coreservice.modules.infra.service.file.InfFileCoreService;
 import cn.iocoder.yudao.coreservice.modules.member.dal.dataobject.user.MbrUserDO;
 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
@@ -10,8 +11,7 @@ import cn.iocoder.yudao.userserver.modules.member.controller.user.vo.MbrUserInfo
 import cn.iocoder.yudao.userserver.modules.member.controller.user.vo.MbrUserUpdateMobileReqVO;
 import cn.iocoder.yudao.userserver.modules.member.dal.mysql.user.MbrUserMapper;
 import cn.iocoder.yudao.userserver.modules.member.service.user.impl.MbrUserServiceImpl;
-import cn.iocoder.yudao.userserver.modules.system.controller.auth.vo.SysAuthSendSmsReqVO;
-import cn.iocoder.yudao.userserver.modules.system.enums.sms.SysSmsSceneEnum;
+import cn.iocoder.yudao.userserver.modules.system.dal.dataobject.sms.SysSmsCodeDO;
 import cn.iocoder.yudao.userserver.modules.system.service.auth.impl.SysAuthServiceImpl;
 import cn.iocoder.yudao.userserver.modules.system.service.sms.SysSmsCodeService;
 import org.junit.jupiter.api.Test;
@@ -27,6 +27,7 @@ import java.util.function.Consumer;
 import static cn.hutool.core.util.RandomUtil.*;
 import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
 import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomString;
+import static cn.iocoder.yudao.userserver.modules.system.enums.sms.SysSmsSceneEnum.CHANGE_MOBILE_BY_SMS;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.mockito.Mockito.*;
 
@@ -115,23 +116,24 @@ public class MbrUserServiceImplTest extends BaseDbAndRedisUnitTest {
         userDO.setMobile(oldMobile);
         userMapper.insert(userDO);
 
-        // 验证旧手机
-        sysSmsCodeService.sendSmsCodeLogin(userDO.getId());
 
-        // 验证旧手机验证码是否正确
-        sysSmsCodeService.useSmsCode(oldMobile,SysSmsSceneEnum.CHANGE_MOBILE_BY_SMS.getScene(),"123","1.1.1.1");
-        // 验证新手机
-        SysAuthSendSmsReqVO smsReqVO = new SysAuthSendSmsReqVO();
-        smsReqVO.setMobile(oldMobile);
-        smsReqVO.setScene(SysSmsSceneEnum.CHANGE_MOBILE_BY_SMS.getScene());
-        sysSmsCodeService.sendSmsNewCode(smsReqVO);
+        // 旧手机和旧验证码
+        SysSmsCodeDO codeDO = new SysSmsCodeDO();
+        String oldCode = RandomUtil.randomString(4);
+        codeDO.setMobile(userDO.getMobile());
+        codeDO.setCode(oldCode);
+        codeDO.setScene(CHANGE_MOBILE_BY_SMS.getScene());
+        codeDO.setUsed(Boolean.FALSE);
+        when(sysSmsCodeService.checkCodeIsExpired(codeDO.getMobile(),codeDO.getCode(),codeDO.getScene())).thenReturn(codeDO);
 
         // 更新手机号
         String newMobile = randomNumbers(11);
-        String code = randomNumbers(4);
+        String newCode = randomNumbers(4);
         MbrUserUpdateMobileReqVO reqVO = new MbrUserUpdateMobileReqVO();
         reqVO.setMobile(newMobile);
-        reqVO.setCode(code);
+        reqVO.setCode(newCode);
+        reqVO.setOldMobile(oldMobile);
+        reqVO.setOldCode(oldCode);
         mbrUserService.updateMobile(userDO.getId(),reqVO);
 
         assertEquals(mbrUserService.getUser(userDO.getId()).getMobile(),newMobile);

+ 5 - 8
yudao-user-server/src/test/java/cn/iocoder/yudao/userserver/modules/system/service/SysAuthServiceTest.java

@@ -23,7 +23,6 @@ import org.springframework.security.authentication.AuthenticationManager;
 import org.springframework.security.crypto.password.PasswordEncoder;
 
 import javax.annotation.Resource;
-import java.util.concurrent.TimeUnit;
 import java.util.function.Consumer;
 
 import static cn.hutool.core.util.RandomUtil.randomEle;
@@ -99,17 +98,15 @@ public class SysAuthServiceTest extends BaseDbAndRedisUnitTest {
         // 随机验证码
         String code = randomNumbers(4);
 
-        MbrAuthResetPasswordReqVO reqVO = MbrAuthResetPasswordReqVO.builder()
-                .password(password)
-                .code(code)
-                .build();
-        // 放入code+手机号
-        stringRedisTemplate.opsForValue().set(code,userDO.getMobile(),10, TimeUnit.MINUTES);
-
         // mock
         when(passwordEncoder.encode(password)).thenReturn(password);
 
         // 更新用户密码
+        MbrAuthResetPasswordReqVO reqVO = new MbrAuthResetPasswordReqVO();
+        reqVO.setMobile(userDO.getMobile());
+        reqVO.setPassword(password);
+        reqVO.setCode(code);
+
         authService.resetPassword(reqVO);
         assertEquals(mbrUserMapper.selectById(userDO.getId()).getPassword(),password);
     }