Commit 8d22ed8bea2b1bdab0d90113bcaab0f3437a0734

Authored by 杨宇庆
Committed by 芋道源码
1 parent 182511b6

!1156 feat: 支持短信重置后台密码

* feat: 支持短信重置后台密码
* 重构管理后台验证码的验证流程
Showing 11 changed files with 154 additions and 51 deletions
yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java
@@ -43,6 +43,7 @@ public interface ErrorCodeConstants { @@ -43,6 +43,7 @@ public interface ErrorCodeConstants {
43 ErrorCode USER_IS_DISABLE = new ErrorCode(1_002_003_006, "名字为【{}】的用户已被禁用"); 43 ErrorCode USER_IS_DISABLE = new ErrorCode(1_002_003_006, "名字为【{}】的用户已被禁用");
44 ErrorCode USER_COUNT_MAX = new ErrorCode(1_002_003_008, "创建用户失败,原因:超过租户最大租户配额({})!"); 44 ErrorCode USER_COUNT_MAX = new ErrorCode(1_002_003_008, "创建用户失败,原因:超过租户最大租户配额({})!");
45 ErrorCode USER_IMPORT_INIT_PASSWORD = new ErrorCode(1_002_003_009, "初始密码不能为空"); 45 ErrorCode USER_IMPORT_INIT_PASSWORD = new ErrorCode(1_002_003_009, "初始密码不能为空");
  46 + ErrorCode USER_MOBILE_NOT_EXISTS = new ErrorCode(1_002_003_010, "该手机号尚未注册");
46 47
47 // ========== 部门模块 1-002-004-000 ========== 48 // ========== 部门模块 1-002-004-000 ==========
48 ErrorCode DEPT_NAME_DUPLICATE = new ErrorCode(1_002_004_000, "已经存在该名字的部门"); 49 ErrorCode DEPT_NAME_DUPLICATE = new ErrorCode(1_002_004_000, "已经存在该名字的部门");
yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/sms/SmsSceneEnum.java
@@ -21,7 +21,9 @@ public enum SmsSceneEnum implements IntArrayValuable { @@ -21,7 +21,9 @@ public enum SmsSceneEnum implements IntArrayValuable {
21 MEMBER_UPDATE_PASSWORD(3, "user-update-password", "会员用户 - 修改密码"), 21 MEMBER_UPDATE_PASSWORD(3, "user-update-password", "会员用户 - 修改密码"),
22 MEMBER_RESET_PASSWORD(4, "user-reset-password", "会员用户 - 忘记密码"), 22 MEMBER_RESET_PASSWORD(4, "user-reset-password", "会员用户 - 忘记密码"),
23 23
24 - ADMIN_MEMBER_LOGIN(21, "admin-sms-login", "后台用户 - 手机号登录"); 24 + ADMIN_MEMBER_LOGIN(21, "admin-sms-login", "后台用户 - 手机号登录"),
  25 + ADMIN_MEMBER_REGISTER(22, "admin-sms-register", "后台用户 - 手机号注册"),
  26 + ADMIN_MEMBER_RESET_PASSWORD(23, "admin-reset-password", "后台用户 - 忘记密码");
25 27
26 public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(SmsSceneEnum::getScene).toArray(); 28 public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(SmsSceneEnum::getScene).toArray();
27 29
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/AuthController.java
@@ -7,7 +7,14 @@ import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; @@ -7,7 +7,14 @@ import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
7 import cn.iocoder.yudao.framework.common.pojo.CommonResult; 7 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
8 import cn.iocoder.yudao.framework.security.config.SecurityProperties; 8 import cn.iocoder.yudao.framework.security.config.SecurityProperties;
9 import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; 9 import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
10 -import cn.iocoder.yudao.module.system.controller.admin.auth.vo.*; 10 +import cn.iocoder.yudao.module.system.controller.admin.auth.vo.AuthLoginReqVO;
  11 +import cn.iocoder.yudao.module.system.controller.admin.auth.vo.AuthLoginRespVO;
  12 +import cn.iocoder.yudao.module.system.controller.admin.auth.vo.AuthPermissionInfoRespVO;
  13 +import cn.iocoder.yudao.module.system.controller.admin.auth.vo.AuthRegisterReqVO;
  14 +import cn.iocoder.yudao.module.system.controller.admin.auth.vo.AuthResetPasswordReqVO;
  15 +import cn.iocoder.yudao.module.system.controller.admin.auth.vo.AuthSmsLoginReqVO;
  16 +import cn.iocoder.yudao.module.system.controller.admin.auth.vo.AuthSmsSendReqVO;
  17 +import cn.iocoder.yudao.module.system.controller.admin.auth.vo.AuthSocialLoginReqVO;
11 import cn.iocoder.yudao.module.system.convert.auth.AuthConvert; 18 import cn.iocoder.yudao.module.system.convert.auth.AuthConvert;
12 import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO; 19 import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO;
13 import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO; 20 import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO;
@@ -23,14 +30,19 @@ import io.swagger.v3.oas.annotations.Operation; @@ -23,14 +30,19 @@ import io.swagger.v3.oas.annotations.Operation;
23 import io.swagger.v3.oas.annotations.Parameter; 30 import io.swagger.v3.oas.annotations.Parameter;
24 import io.swagger.v3.oas.annotations.Parameters; 31 import io.swagger.v3.oas.annotations.Parameters;
25 import io.swagger.v3.oas.annotations.tags.Tag; 32 import io.swagger.v3.oas.annotations.tags.Tag;
26 -import lombok.extern.slf4j.Slf4j;  
27 -import org.springframework.validation.annotation.Validated;  
28 -import org.springframework.web.bind.annotation.*;  
29 -  
30 import jakarta.annotation.Resource; 33 import jakarta.annotation.Resource;
31 import jakarta.annotation.security.PermitAll; 34 import jakarta.annotation.security.PermitAll;
32 import jakarta.servlet.http.HttpServletRequest; 35 import jakarta.servlet.http.HttpServletRequest;
33 import jakarta.validation.Valid; 36 import jakarta.validation.Valid;
  37 +import lombok.extern.slf4j.Slf4j;
  38 +import org.springframework.validation.annotation.Validated;
  39 +import org.springframework.web.bind.annotation.GetMapping;
  40 +import org.springframework.web.bind.annotation.PostMapping;
  41 +import org.springframework.web.bind.annotation.RequestBody;
  42 +import org.springframework.web.bind.annotation.RequestMapping;
  43 +import org.springframework.web.bind.annotation.RequestParam;
  44 +import org.springframework.web.bind.annotation.RestController;
  45 +
34 import java.util.Collections; 46 import java.util.Collections;
35 import java.util.List; 47 import java.util.List;
36 import java.util.Set; 48 import java.util.Set;
@@ -139,6 +151,14 @@ public class AuthController { @@ -139,6 +151,14 @@ public class AuthController {
139 return success(true); 151 return success(true);
140 } 152 }
141 153
  154 + @PostMapping("/reset-password")
  155 + @PermitAll
  156 + @Operation(summary = "重置密码")
  157 + public CommonResult<Boolean> resetPassword(@RequestBody @Valid AuthResetPasswordReqVO reqVO) {
  158 + authService.resetPassword(reqVO);
  159 + return success(true);
  160 + }
  161 +
142 // ========== 社交登录相关 ========== 162 // ========== 社交登录相关 ==========
143 163
144 @GetMapping("/social-auth-redirect") 164 @GetMapping("/social-auth-redirect")
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/AuthLoginReqVO.java
@@ -19,7 +19,7 @@ import jakarta.validation.constraints.Pattern; @@ -19,7 +19,7 @@ import jakarta.validation.constraints.Pattern;
19 @NoArgsConstructor 19 @NoArgsConstructor
20 @AllArgsConstructor 20 @AllArgsConstructor
21 @Builder 21 @Builder
22 -public class AuthLoginReqVO { 22 +public class AuthLoginReqVO extends CaptchaVerificationReqVO {
23 23
24 @Schema(description = "账号", requiredMode = Schema.RequiredMode.REQUIRED, example = "yudaoyuanma") 24 @Schema(description = "账号", requiredMode = Schema.RequiredMode.REQUIRED, example = "yudaoyuanma")
25 @NotEmpty(message = "登录账号不能为空") 25 @NotEmpty(message = "登录账号不能为空")
@@ -32,13 +32,6 @@ public class AuthLoginReqVO { @@ -32,13 +32,6 @@ public class AuthLoginReqVO {
32 @Length(min = 4, max = 16, message = "密码长度为 4-16 位") 32 @Length(min = 4, max = 16, message = "密码长度为 4-16 位")
33 private String password; 33 private String password;
34 34
35 - // ========== 图片验证码相关 ==========  
36 -  
37 - @Schema(description = "验证码,验证码开启时,需要传递", requiredMode = Schema.RequiredMode.REQUIRED,  
38 - example = "PfcH6mgr8tpXuMWFjvW6YVaqrswIuwmWI5dsVZSg7sGpWtDCUbHuDEXl3cFB1+VvCC/rAkSwK8Fad52FSuncVg==")  
39 - @NotEmpty(message = "验证码不能为空", groups = CodeEnableGroup.class)  
40 - private String captchaVerification;  
41 -  
42 // ========== 绑定社交登录时,需要传递如下参数 ========== 35 // ========== 绑定社交登录时,需要传递如下参数 ==========
43 36
44 @Schema(description = "社交平台的类型,参见 SocialTypeEnum 枚举值", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") 37 @Schema(description = "社交平台的类型,参见 SocialTypeEnum 枚举值", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
@@ -51,11 +44,6 @@ public class AuthLoginReqVO { @@ -51,11 +44,6 @@ public class AuthLoginReqVO {
51 @Schema(description = "state", requiredMode = Schema.RequiredMode.REQUIRED, example = "9b2ffbc1-7425-4155-9894-9d5c08541d62") 44 @Schema(description = "state", requiredMode = Schema.RequiredMode.REQUIRED, example = "9b2ffbc1-7425-4155-9894-9d5c08541d62")
52 private String socialState; 45 private String socialState;
53 46
54 - /**  
55 - * 开启验证码的 Group  
56 - */  
57 - public interface CodeEnableGroup {}  
58 -  
59 @AssertTrue(message = "授权码不能为空") 47 @AssertTrue(message = "授权码不能为空")
60 public boolean isSocialCodeValid() { 48 public boolean isSocialCodeValid() {
61 return socialType == null || StrUtil.isNotEmpty(socialCode); 49 return socialType == null || StrUtil.isNotEmpty(socialCode);
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/AuthRegisterReqVO.java
@@ -9,7 +9,7 @@ import jakarta.validation.constraints.*; @@ -9,7 +9,7 @@ import jakarta.validation.constraints.*;
9 9
10 @Schema(description = "管理后台 - Register Request VO") 10 @Schema(description = "管理后台 - Register Request VO")
11 @Data 11 @Data
12 -public class AuthRegisterReqVO { 12 +public class AuthRegisterReqVO extends CaptchaVerificationReqVO {
13 13
14 @Schema(description = "用户账号", requiredMode = Schema.RequiredMode.REQUIRED, example = "yudao") 14 @Schema(description = "用户账号", requiredMode = Schema.RequiredMode.REQUIRED, example = "yudao")
15 @NotBlank(message = "用户账号不能为空") 15 @NotBlank(message = "用户账号不能为空")
@@ -26,12 +26,4 @@ public class AuthRegisterReqVO { @@ -26,12 +26,4 @@ public class AuthRegisterReqVO {
26 @NotEmpty(message = "密码不能为空") 26 @NotEmpty(message = "密码不能为空")
27 @Length(min = 4, max = 16, message = "密码长度为 4-16 位") 27 @Length(min = 4, max = 16, message = "密码长度为 4-16 位")
28 private String password; 28 private String password;
29 -  
30 - // ========== 图片验证码相关 ==========  
31 -  
32 - @Schema(description = "验证码,验证码开启时,需要传递", requiredMode = Schema.RequiredMode.REQUIRED,  
33 - example = "PfcH6mgr8tpXuMWFjvW6YVaqrswIuwmWI5dsVZSg7sGpWtDCUbHuDEXl3cFB1+VvCC/rAkSwK8Fad52FSuncVg==")  
34 - @NotEmpty(message = "验证码不能为空", groups = AuthLoginReqVO.CodeEnableGroup.class)  
35 - private String captchaVerification;  
36 -  
37 } 29 }
38 \ No newline at end of file 30 \ No newline at end of file
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/AuthResetPasswordReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.system.controller.admin.auth.vo;
  2 +
  3 +import cn.iocoder.yudao.framework.common.validation.Mobile;
  4 +import io.swagger.v3.oas.annotations.media.Schema;
  5 +import jakarta.validation.constraints.NotEmpty;
  6 +import lombok.AllArgsConstructor;
  7 +import lombok.Builder;
  8 +import lombok.Data;
  9 +import lombok.NoArgsConstructor;
  10 +import org.hibernate.validator.constraints.Length;
  11 +
  12 +@Schema(description = "管理后台 - 短信重置账号密码 Request VO")
  13 +@Data
  14 +@NoArgsConstructor
  15 +@AllArgsConstructor
  16 +@Builder
  17 +public class AuthResetPasswordReqVO {
  18 +
  19 + @Schema(description = "密码", requiredMode = Schema.RequiredMode.REQUIRED, example = "1234")
  20 + @NotEmpty(message = "密码不能为空")
  21 + @Length(min = 4, max = 16, message = "密码长度为 4-16 位")
  22 + private String password;
  23 +
  24 + @Schema(description = "手机号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13312341234")
  25 + @NotEmpty(message = "手机号不能为空")
  26 + @Mobile
  27 + private String mobile;
  28 +
  29 + @Schema(description = "手机短信验证码", requiredMode = Schema.RequiredMode.REQUIRED, example = "123456")
  30 + @NotEmpty(message = "手机手机短信验证码不能为空")
  31 + private String code;
  32 +}
0 \ No newline at end of file 33 \ No newline at end of file
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/AuthSmsSendReqVO.java
@@ -17,7 +17,7 @@ import jakarta.validation.constraints.NotNull; @@ -17,7 +17,7 @@ import jakarta.validation.constraints.NotNull;
17 @NoArgsConstructor 17 @NoArgsConstructor
18 @AllArgsConstructor 18 @AllArgsConstructor
19 @Builder 19 @Builder
20 -public class AuthSmsSendReqVO { 20 +public class AuthSmsSendReqVO extends CaptchaVerificationReqVO {
21 21
22 @Schema(description = "手机号", requiredMode = Schema.RequiredMode.REQUIRED, example = "yudaoyuanma") 22 @Schema(description = "手机号", requiredMode = Schema.RequiredMode.REQUIRED, example = "yudaoyuanma")
23 @NotEmpty(message = "手机号不能为空") 23 @NotEmpty(message = "手机号不能为空")
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/CaptchaVerificationReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.system.controller.admin.auth.vo;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import jakarta.validation.constraints.NotEmpty;
  5 +import lombok.Data;
  6 +
  7 +@Schema(description = "管理后台 - 验证码 Request VO")
  8 +@Data
  9 +public class CaptchaVerificationReqVO {
  10 +
  11 + // ========== 图片验证码相关 ==========
  12 + @Schema(description = "验证码,验证码开启时,需要传递", requiredMode = Schema.RequiredMode.REQUIRED,
  13 + example = "PfcH6mgr8tpXuMWFjvW6YVaqrswIuwmWI5dsVZSg7sGpWtDCUbHuDEXl3cFB1+VvCC/rAkSwK8Fad52FSuncVg==")
  14 + @NotEmpty(message = "验证码不能为空", groups = CodeEnableGroup.class)
  15 + private String captchaVerification;
  16 +
  17 + /**
  18 + * 开启验证码的 Group
  19 + */
  20 + public interface CodeEnableGroup {
  21 + }
  22 +}
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthService.java
@@ -52,7 +52,7 @@ public interface AdminAuthService { @@ -52,7 +52,7 @@ public interface AdminAuthService {
52 * @param reqVO 登录信息 52 * @param reqVO 登录信息
53 * @return 登录结果 53 * @return 登录结果
54 */ 54 */
55 - AuthLoginRespVO smsLogin(AuthSmsLoginReqVO reqVO) ; 55 + AuthLoginRespVO smsLogin(AuthSmsLoginReqVO reqVO);
56 56
57 /** 57 /**
58 * 社交快捷登录,使用 code 授权码 58 * 社交快捷登录,使用 code 授权码
@@ -78,4 +78,11 @@ public interface AdminAuthService { @@ -78,4 +78,11 @@ public interface AdminAuthService {
78 */ 78 */
79 AuthLoginRespVO register(AuthRegisterReqVO createReqVO); 79 AuthLoginRespVO register(AuthRegisterReqVO createReqVO);
80 80
  81 + /**
  82 + * 重置密码
  83 + *
  84 + * @param reqVO 验证码信息
  85 + */
  86 + void resetPassword(AuthResetPasswordReqVO reqVO);
  87 +
81 } 88 }
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthServiceImpl.java
@@ -8,9 +8,17 @@ import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; @@ -8,9 +8,17 @@ import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
8 import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils; 8 import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils;
9 import cn.iocoder.yudao.module.system.api.logger.dto.LoginLogCreateReqDTO; 9 import cn.iocoder.yudao.module.system.api.logger.dto.LoginLogCreateReqDTO;
10 import cn.iocoder.yudao.module.system.api.sms.SmsCodeApi; 10 import cn.iocoder.yudao.module.system.api.sms.SmsCodeApi;
  11 +import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeUseReqDTO;
11 import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO; 12 import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO;
12 import cn.iocoder.yudao.module.system.api.social.dto.SocialUserRespDTO; 13 import cn.iocoder.yudao.module.system.api.social.dto.SocialUserRespDTO;
13 -import cn.iocoder.yudao.module.system.controller.admin.auth.vo.*; 14 +import cn.iocoder.yudao.module.system.controller.admin.auth.vo.AuthLoginReqVO;
  15 +import cn.iocoder.yudao.module.system.controller.admin.auth.vo.AuthLoginRespVO;
  16 +import cn.iocoder.yudao.module.system.controller.admin.auth.vo.AuthRegisterReqVO;
  17 +import cn.iocoder.yudao.module.system.controller.admin.auth.vo.AuthResetPasswordReqVO;
  18 +import cn.iocoder.yudao.module.system.controller.admin.auth.vo.AuthSmsLoginReqVO;
  19 +import cn.iocoder.yudao.module.system.controller.admin.auth.vo.AuthSmsSendReqVO;
  20 +import cn.iocoder.yudao.module.system.controller.admin.auth.vo.AuthSocialLoginReqVO;
  21 +import cn.iocoder.yudao.module.system.controller.admin.auth.vo.CaptchaVerificationReqVO;
14 import cn.iocoder.yudao.module.system.convert.auth.AuthConvert; 22 import cn.iocoder.yudao.module.system.convert.auth.AuthConvert;
15 import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2AccessTokenDO; 23 import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2AccessTokenDO;
16 import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; 24 import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
@@ -22,6 +30,7 @@ import cn.iocoder.yudao.module.system.service.logger.LoginLogService; @@ -22,6 +30,7 @@ import cn.iocoder.yudao.module.system.service.logger.LoginLogService;
22 import cn.iocoder.yudao.module.system.service.member.MemberService; 30 import cn.iocoder.yudao.module.system.service.member.MemberService;
23 import cn.iocoder.yudao.module.system.service.oauth2.OAuth2TokenService; 31 import cn.iocoder.yudao.module.system.service.oauth2.OAuth2TokenService;
24 import cn.iocoder.yudao.module.system.service.social.SocialUserService; 32 import cn.iocoder.yudao.module.system.service.social.SocialUserService;
  33 +import cn.iocoder.yudao.module.system.service.tenant.TenantService;
25 import cn.iocoder.yudao.module.system.service.user.AdminUserService; 34 import cn.iocoder.yudao.module.system.service.user.AdminUserService;
26 import com.google.common.annotations.VisibleForTesting; 35 import com.google.common.annotations.VisibleForTesting;
27 import com.xingyuv.captcha.model.common.ResponseModel; 36 import com.xingyuv.captcha.model.common.ResponseModel;
@@ -32,12 +41,20 @@ import jakarta.validation.Validator; @@ -32,12 +41,20 @@ import jakarta.validation.Validator;
32 import lombok.extern.slf4j.Slf4j; 41 import lombok.extern.slf4j.Slf4j;
33 import org.springframework.beans.factory.annotation.Value; 42 import org.springframework.beans.factory.annotation.Value;
34 import org.springframework.stereotype.Service; 43 import org.springframework.stereotype.Service;
  44 +import org.springframework.transaction.annotation.Transactional;
35 45
36 import java.util.Objects; 46 import java.util.Objects;
37 47
38 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 48 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
39 import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP; 49 import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP;
40 -import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; 50 +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.AUTH_LOGIN_BAD_CREDENTIALS;
  51 +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.AUTH_LOGIN_CAPTCHA_CODE_ERROR;
  52 +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.AUTH_LOGIN_USER_DISABLED;
  53 +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.AUTH_MOBILE_NOT_EXISTS;
  54 +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.AUTH_REGISTER_CAPTCHA_CODE_ERROR;
  55 +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.AUTH_THIRD_LOGIN_NOT_BIND;
  56 +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.USER_MOBILE_NOT_EXISTS;
  57 +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.USER_NOT_EXISTS;
41 58
42 /** 59 /**
43 * Auth Service 实现类 60 * Auth Service 实现类
@@ -64,6 +81,8 @@ public class AdminAuthServiceImpl implements AdminAuthService { @@ -64,6 +81,8 @@ public class AdminAuthServiceImpl implements AdminAuthService {
64 private CaptchaService captchaService; 81 private CaptchaService captchaService;
65 @Resource 82 @Resource
66 private SmsCodeApi smsCodeApi; 83 private SmsCodeApi smsCodeApi;
  84 + @Resource
  85 + private TenantService tenantService;
67 86
68 /** 87 /**
69 * 验证码的开关,默认为 true 88 * 验证码的开关,默认为 true
@@ -111,6 +130,13 @@ public class AdminAuthServiceImpl implements AdminAuthService { @@ -111,6 +130,13 @@ public class AdminAuthServiceImpl implements AdminAuthService {
111 130
112 @Override 131 @Override
113 public void sendSmsCode(AuthSmsSendReqVO reqVO) { 132 public void sendSmsCode(AuthSmsSendReqVO reqVO) {
  133 + // 如果是重置密码场景,需要校验图形验证码是否正确
  134 + if (Objects.equals(SmsSceneEnum.ADMIN_MEMBER_RESET_PASSWORD.getScene(), reqVO.getScene())) {
  135 + ResponseModel response = doValidateCaptcha(reqVO);
  136 + if (!response.isSuccess()) {
  137 + throw exception(AUTH_REGISTER_CAPTCHA_CODE_ERROR, response.getRepMsg());
  138 + }
  139 + }
114 // 登录场景,验证是否存在 140 // 登录场景,验证是否存在
115 if (userService.getUserByMobile(reqVO.getMobile()) == null) { 141 if (userService.getUserByMobile(reqVO.getMobile()) == null) {
116 throw exception(AUTH_MOBILE_NOT_EXISTS); 142 throw exception(AUTH_MOBILE_NOT_EXISTS);
@@ -174,16 +200,8 @@ public class AdminAuthServiceImpl implements AdminAuthService { @@ -174,16 +200,8 @@ public class AdminAuthServiceImpl implements AdminAuthService {
174 200
175 @VisibleForTesting 201 @VisibleForTesting
176 void validateCaptcha(AuthLoginReqVO reqVO) { 202 void validateCaptcha(AuthLoginReqVO reqVO) {
177 - // 如果验证码关闭,则不进行校验  
178 - if (!captchaEnable) {  
179 - return;  
180 - } 203 + ResponseModel response = doValidateCaptcha(reqVO);
181 // 校验验证码 204 // 校验验证码
182 - ValidationUtils.validate(validator, reqVO, AuthLoginReqVO.CodeEnableGroup.class);  
183 - CaptchaVO captchaVO = new CaptchaVO();  
184 - captchaVO.setCaptchaVerification(reqVO.getCaptchaVerification());  
185 - ResponseModel response = captchaService.verification(captchaVO);  
186 - // 验证不通过  
187 if (!response.isSuccess()) { 205 if (!response.isSuccess()) {
188 // 创建登录失败日志(验证码不正确) 206 // 创建登录失败日志(验证码不正确)
189 createLoginLog(null, reqVO.getUsername(), LoginLogTypeEnum.LOGIN_USERNAME, LoginResultEnum.CAPTCHA_CODE_ERROR); 207 createLoginLog(null, reqVO.getUsername(), LoginLogTypeEnum.LOGIN_USERNAME, LoginResultEnum.CAPTCHA_CODE_ERROR);
@@ -191,6 +209,17 @@ public class AdminAuthServiceImpl implements AdminAuthService { @@ -191,6 +209,17 @@ public class AdminAuthServiceImpl implements AdminAuthService {
191 } 209 }
192 } 210 }
193 211
  212 + private ResponseModel doValidateCaptcha(CaptchaVerificationReqVO reqVO) {
  213 + // 如果验证码关闭,则不进行校验
  214 + if (!captchaEnable) {
  215 + return ResponseModel.success();
  216 + }
  217 + ValidationUtils.validate(validator, reqVO, CaptchaVerificationReqVO.CodeEnableGroup.class);
  218 + CaptchaVO captchaVO = new CaptchaVO();
  219 + captchaVO.setCaptchaVerification(reqVO.getCaptchaVerification());
  220 + return captchaService.verification(captchaVO);
  221 + }
  222 +
194 private AuthLoginRespVO createTokenAfterLoginSuccess(Long userId, String username, LoginLogTypeEnum logType) { 223 private AuthLoginRespVO createTokenAfterLoginSuccess(Long userId, String username, LoginLogTypeEnum logType) {
195 // 插入登陆日志 224 // 插入登陆日志
196 createLoginLog(userId, username, logType, LoginResultEnum.SUCCESS); 225 createLoginLog(userId, username, logType, LoginResultEnum.SUCCESS);
@@ -261,19 +290,28 @@ public class AdminAuthServiceImpl implements AdminAuthService { @@ -261,19 +290,28 @@ public class AdminAuthServiceImpl implements AdminAuthService {
261 290
262 @VisibleForTesting 291 @VisibleForTesting
263 void validateCaptcha(AuthRegisterReqVO reqVO) { 292 void validateCaptcha(AuthRegisterReqVO reqVO) {
264 - // 如果验证码关闭,则不进行校验  
265 - if (!captchaEnable) {  
266 - return;  
267 - }  
268 - // 校验验证码  
269 - ValidationUtils.validate(validator, reqVO, AuthLoginReqVO.CodeEnableGroup.class);  
270 - CaptchaVO captchaVO = new CaptchaVO();  
271 - captchaVO.setCaptchaVerification(reqVO.getCaptchaVerification());  
272 - ResponseModel response = captchaService.verification(captchaVO); 293 + ResponseModel response = doValidateCaptcha(reqVO);
273 // 验证不通过 294 // 验证不通过
274 if (!response.isSuccess()) { 295 if (!response.isSuccess()) {
275 throw exception(AUTH_REGISTER_CAPTCHA_CODE_ERROR, response.getRepMsg()); 296 throw exception(AUTH_REGISTER_CAPTCHA_CODE_ERROR, response.getRepMsg());
276 } 297 }
277 } 298 }
278 299
  300 + @Override
  301 + @Transactional(rollbackFor = Exception.class)
  302 + public void resetPassword(AuthResetPasswordReqVO reqVO) {
  303 + AdminUserDO userByMobile = userService.getUserByMobile(reqVO.getMobile());
  304 + if (userByMobile == null) {
  305 + throw exception(USER_MOBILE_NOT_EXISTS);
  306 + }
  307 +
  308 + smsCodeApi.useSmsCode(new SmsCodeUseReqDTO()
  309 + .setCode(reqVO.getCode())
  310 + .setMobile(reqVO.getMobile())
  311 + .setScene(SmsSceneEnum.ADMIN_MEMBER_RESET_PASSWORD.getScene())
  312 + .setUsedIp(getClientIP())
  313 + );
  314 +
  315 + userService.updateUserPassword(userByMobile.getId(), reqVO.getPassword());
  316 + }
279 } 317 }
yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthServiceImplTest.java
@@ -296,7 +296,8 @@ public class AdminAuthServiceImplTest extends BaseDbUnitTest { @@ -296,7 +296,8 @@ public class AdminAuthServiceImplTest extends BaseDbUnitTest {
296 @Test 296 @Test
297 public void testValidateCaptcha_constraintViolationException() { 297 public void testValidateCaptcha_constraintViolationException() {
298 // 准备参数 298 // 准备参数
299 - AuthLoginReqVO reqVO = randomPojo(AuthLoginReqVO.class).setCaptchaVerification(null); 299 + AuthLoginReqVO reqVO = randomPojo(AuthLoginReqVO.class);
  300 + reqVO.setCaptchaVerification(null);
300 301
301 // mock 验证码打开 302 // mock 验证码打开
302 ReflectUtil.setFieldValue(authService, "captchaEnable", true); 303 ReflectUtil.setFieldValue(authService, "captchaEnable", true);