From 21fbe91e39f029174377699110d149d1d2e684c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AE=8B=E5=A4=A9?= <2982176321@qq.com> Date: Sat, 25 Dec 2021 00:05:21 +0800 Subject: [PATCH] =?UTF-8?q?update=20=E7=94=A8=E6=88=B7=E4=B8=AD=E5=BF=83?= =?UTF-8?q?=E5=AF=86=E7=A0=81=E6=93=8D=E4=BD=9C=E4=BF=AE=E6=94=B9=E9=80=BB?= =?UTF-8?q?=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/application-local.yaml | 14 ++++---- .../service/user/impl/MbrUserServiceImpl.java | 27 ++++++-------- .../system/enums/SysErrorCodeConstants.java | 2 +- .../system/service/sms/SysSmsCodeService.java | 22 ++++++------ .../sms/impl/SysSmsCodeServiceImpl.java | 35 ++++++++----------- .../service/MbrUserServiceImplTest.java | 28 ++++++++------- .../system/service/SysAuthServiceTest.java | 13 +++---- 7 files changed, 64 insertions(+), 77 deletions(-) diff --git a/yudao-admin-server/src/main/resources/application-local.yaml b/yudao-admin-server/src/main/resources/application-local.yaml index 54d5447d..89d1f357 100644 --- a/yudao-admin-server/src/main/resources/application-local.yaml +++ b/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: diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/member/service/user/impl/MbrUserServiceImpl.java b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/member/service/user/impl/MbrUserServiceImpl.java index d31ed9ee..ee769069 100644 --- a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/member/service/user/impl/MbrUserServiceImpl.java +++ b/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); } diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/enums/SysErrorCodeConstants.java b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/enums/SysErrorCodeConstants.java index c37dca9b..05ae0ed3 100644 --- a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/enums/SysErrorCodeConstants.java +++ b/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, "用户不存在"); diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/service/sms/SysSmsCodeService.java b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/service/sms/SysSmsCodeService.java index 160527d3..8a052c76 100644 --- a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/service/sms/SysSmsCodeService.java +++ b/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); - } diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/service/sms/impl/SysSmsCodeServiceImpl.java b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/service/sms/impl/SysSmsCodeServiceImpl.java index c7aa98f9..d0fd64df 100644 --- a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/service/sms/impl/SysSmsCodeServiceImpl.java +++ b/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; + } } diff --git a/yudao-user-server/src/test/java/cn/iocoder/yudao/userserver/modules/member/service/MbrUserServiceImplTest.java b/yudao-user-server/src/test/java/cn/iocoder/yudao/userserver/modules/member/service/MbrUserServiceImplTest.java index 05571ba2..68f41643 100644 --- a/yudao-user-server/src/test/java/cn/iocoder/yudao/userserver/modules/member/service/MbrUserServiceImplTest.java +++ b/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); diff --git a/yudao-user-server/src/test/java/cn/iocoder/yudao/userserver/modules/system/service/SysAuthServiceTest.java b/yudao-user-server/src/test/java/cn/iocoder/yudao/userserver/modules/system/service/SysAuthServiceTest.java index 83cf35be..4c8b953c 100644 --- a/yudao-user-server/src/test/java/cn/iocoder/yudao/userserver/modules/system/service/SysAuthServiceTest.java +++ b/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); }