Commit 28b10b35d5ddcd4f597d347b47a6f752bc8bf345
1 parent
afd5a9c8
【代码优化】注册的逻辑实现
Showing
7 changed files
with
81 additions
and
54 deletions
yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java
| ... | ... | @@ -15,6 +15,7 @@ public interface ErrorCodeConstants { |
| 15 | 15 | ErrorCode AUTH_LOGIN_CAPTCHA_CODE_ERROR = new ErrorCode(1_002_000_004, "验证码不正确,原因:{}"); |
| 16 | 16 | ErrorCode AUTH_THIRD_LOGIN_NOT_BIND = new ErrorCode(1_002_000_005, "未绑定账号,需要进行绑定"); |
| 17 | 17 | ErrorCode AUTH_MOBILE_NOT_EXISTS = new ErrorCode(1_002_000_007, "手机号不存在"); |
| 18 | + ErrorCode AUTH_REGISTER_CAPTCHA_CODE_ERROR = new ErrorCode(1_002_000_008, "验证码不正确,原因:{}"); | |
| 18 | 19 | |
| 19 | 20 | // ========== 菜单模块 1-002-001-000 ========== |
| 20 | 21 | ErrorCode MENU_NAME_DUPLICATE = new ErrorCode(1_002_001_000, "已经存在该名字的菜单"); | ... | ... |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/AuthController.java
| ... | ... | @@ -115,6 +115,13 @@ public class AuthController { |
| 115 | 115 | return success(AuthConvert.INSTANCE.convert(user, roles, menuList)); |
| 116 | 116 | } |
| 117 | 117 | |
| 118 | + @PostMapping("/register") | |
| 119 | + @PermitAll | |
| 120 | + @Operation(summary = "注册用户") | |
| 121 | + public CommonResult<AuthLoginRespVO> register(@RequestBody @Valid AuthRegisterReqVO registerReqVO) { | |
| 122 | + return success(authService.register(registerReqVO)); | |
| 123 | + } | |
| 124 | + | |
| 118 | 125 | // ========== 短信登录相关 ========== |
| 119 | 126 | |
| 120 | 127 | @PostMapping("/sms-login") |
| ... | ... | @@ -154,10 +161,4 @@ public class AuthController { |
| 154 | 161 | return success(authService.socialLogin(reqVO)); |
| 155 | 162 | } |
| 156 | 163 | |
| 157 | - @PostMapping("/register") | |
| 158 | - @PermitAll | |
| 159 | - @Operation(summary = "注册用户") | |
| 160 | - public CommonResult<AuthLoginRespVO> register(@RequestBody @Valid AuthRegisterReqVO registerReqVO) { | |
| 161 | - return success(authService.register(registerReqVO)); | |
| 162 | - } | |
| 163 | 164 | } | ... | ... |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/AuthRegisterReqVO.java
| ... | ... | @@ -18,16 +18,20 @@ public class AuthRegisterReqVO { |
| 18 | 18 | private String username; |
| 19 | 19 | |
| 20 | 20 | @Schema(description = "用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿") |
| 21 | - @Size(max = 30, message = "用户昵称长度不能超过30个字符") | |
| 21 | + @NotBlank(message = "用户昵称不能为空") | |
| 22 | + @Size(max = 30, message = "用户昵称长度不能超过 30 个字符") | |
| 22 | 23 | private String nickname; |
| 23 | 24 | |
| 24 | 25 | @Schema(description = "密码", requiredMode = Schema.RequiredMode.REQUIRED, example = "123456") |
| 26 | + @NotEmpty(message = "密码不能为空") | |
| 25 | 27 | @Length(min = 4, max = 16, message = "密码长度为 4-16 位") |
| 26 | 28 | private String password; |
| 27 | 29 | |
| 28 | 30 | // ========== 图片验证码相关 ========== |
| 31 | + | |
| 29 | 32 | @Schema(description = "验证码,验证码开启时,需要传递", requiredMode = Schema.RequiredMode.REQUIRED, |
| 30 | 33 | example = "PfcH6mgr8tpXuMWFjvW6YVaqrswIuwmWI5dsVZSg7sGpWtDCUbHuDEXl3cFB1+VvCC/rAkSwK8Fad52FSuncVg==") |
| 31 | 34 | @NotEmpty(message = "验证码不能为空", groups = AuthLoginReqVO.CodeEnableGroup.class) |
| 32 | 35 | private String captchaVerification; |
| 36 | + | |
| 33 | 37 | } |
| 34 | 38 | \ No newline at end of file | ... | ... |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthService.java
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthServiceImpl.java
| ... | ... | @@ -4,7 +4,6 @@ import cn.hutool.core.util.ObjectUtil; |
| 4 | 4 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; |
| 5 | 5 | import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; |
| 6 | 6 | import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils; |
| 7 | -import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | |
| 8 | 7 | import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; |
| 9 | 8 | import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils; |
| 10 | 9 | import cn.iocoder.yudao.module.system.api.logger.dto.LoginLogCreateReqDTO; |
| ... | ... | @@ -15,7 +14,6 @@ import cn.iocoder.yudao.module.system.controller.admin.auth.vo.*; |
| 15 | 14 | import cn.iocoder.yudao.module.system.convert.auth.AuthConvert; |
| 16 | 15 | import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2AccessTokenDO; |
| 17 | 16 | import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; |
| 18 | -import cn.iocoder.yudao.module.system.dal.mysql.user.AdminUserMapper; | |
| 19 | 17 | import cn.iocoder.yudao.module.system.enums.logger.LoginLogTypeEnum; |
| 20 | 18 | import cn.iocoder.yudao.module.system.enums.logger.LoginResultEnum; |
| 21 | 19 | import cn.iocoder.yudao.module.system.enums.oauth2.OAuth2ClientConstants; |
| ... | ... | @@ -24,20 +22,17 @@ import cn.iocoder.yudao.module.system.service.logger.LoginLogService; |
| 24 | 22 | import cn.iocoder.yudao.module.system.service.member.MemberService; |
| 25 | 23 | import cn.iocoder.yudao.module.system.service.oauth2.OAuth2TokenService; |
| 26 | 24 | import cn.iocoder.yudao.module.system.service.social.SocialUserService; |
| 27 | -import cn.iocoder.yudao.module.system.service.tenant.TenantService; | |
| 28 | 25 | import cn.iocoder.yudao.module.system.service.user.AdminUserService; |
| 29 | 26 | import com.google.common.annotations.VisibleForTesting; |
| 30 | 27 | import com.xingyuv.captcha.model.common.ResponseModel; |
| 31 | 28 | import com.xingyuv.captcha.model.vo.CaptchaVO; |
| 32 | 29 | import com.xingyuv.captcha.service.CaptchaService; |
| 30 | +import jakarta.annotation.Resource; | |
| 31 | +import jakarta.validation.Validator; | |
| 33 | 32 | import lombok.extern.slf4j.Slf4j; |
| 34 | 33 | import org.springframework.beans.factory.annotation.Value; |
| 35 | -import org.springframework.context.annotation.Lazy; | |
| 36 | -import org.springframework.security.crypto.password.PasswordEncoder; | |
| 37 | 34 | import org.springframework.stereotype.Service; |
| 38 | 35 | |
| 39 | -import jakarta.annotation.Resource; | |
| 40 | -import jakarta.validation.Validator; | |
| 41 | 36 | import java.util.Objects; |
| 42 | 37 | |
| 43 | 38 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| ... | ... | @@ -69,13 +64,7 @@ public class AdminAuthServiceImpl implements AdminAuthService { |
| 69 | 64 | private CaptchaService captchaService; |
| 70 | 65 | @Resource |
| 71 | 66 | private SmsCodeApi smsCodeApi; |
| 72 | - @Resource | |
| 73 | - @Lazy // 延迟,避免循环依赖报错 | |
| 74 | - private TenantService tenantService; | |
| 75 | - @Resource | |
| 76 | - private AdminUserMapper userMapper; | |
| 77 | - @Resource | |
| 78 | - private PasswordEncoder passwordEncoder; | |
| 67 | + | |
| 79 | 68 | /** |
| 80 | 69 | * 验证码的开关,默认为 true |
| 81 | 70 | */ |
| ... | ... | @@ -258,38 +247,33 @@ public class AdminAuthServiceImpl implements AdminAuthService { |
| 258 | 247 | return UserTypeEnum.ADMIN; |
| 259 | 248 | } |
| 260 | 249 | |
| 261 | - | |
| 250 | + @Override | |
| 262 | 251 | public AuthLoginRespVO register(AuthRegisterReqVO registerReqVO) { |
| 263 | - // 校验验证码 | |
| 264 | - AuthLoginReqVO loginReqVO = BeanUtils.toBean(registerReqVO, AuthLoginReqVO.class); | |
| 265 | - validateCaptcha(loginReqVO); | |
| 266 | - // 校验账户配合 | |
| 267 | - tenantService.handleTenantInfo(tenant -> { | |
| 268 | - long count = userMapper.selectCount(); | |
| 269 | - if (count >= tenant.getAccountCount()) { | |
| 270 | - throw exception(USER_COUNT_MAX, tenant.getAccountCount()); | |
| 271 | - } | |
| 272 | - }); | |
| 273 | - // 校验用户名是否已存在 | |
| 274 | - if (userMapper.selectByUsername(registerReqVO.getUsername()) != null) { | |
| 275 | - throw exception(USER_USERNAME_EXISTS); | |
| 276 | - } | |
| 277 | - // 插入用户 | |
| 278 | - AdminUserDO user = BeanUtils.toBean(registerReqVO, AdminUserDO.class); | |
| 279 | - user.setStatus(CommonStatusEnum.ENABLE.getStatus()); // 默认开启 | |
| 280 | - user.setPassword(encodePassword(registerReqVO.getPassword())); // 加密密码 | |
| 281 | - userMapper.insert(user); | |
| 252 | + // 1. 校验验证码 | |
| 253 | + validateCaptcha(registerReqVO); | |
| 282 | 254 | |
| 283 | - return createTokenAfterLoginSuccess(user.getId(), registerReqVO.getUsername(), LoginLogTypeEnum.LOGIN_USERNAME); | |
| 255 | + // 2. 校验用户名是否已存在 | |
| 256 | + Long userId = userService.registerUser(registerReqVO); | |
| 257 | + | |
| 258 | + // 3. 创建 Token 令牌,记录登录日志 | |
| 259 | + return createTokenAfterLoginSuccess(userId, registerReqVO.getUsername(), LoginLogTypeEnum.LOGIN_USERNAME); | |
| 284 | 260 | } |
| 285 | 261 | |
| 286 | - /** | |
| 287 | - * 对密码进行加密 | |
| 288 | - * | |
| 289 | - * @param password 密码 | |
| 290 | - * @return 加密后的密码 | |
| 291 | - */ | |
| 292 | - private String encodePassword(String password) { | |
| 293 | - return passwordEncoder.encode(password); | |
| 262 | + @VisibleForTesting | |
| 263 | + 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); | |
| 273 | + // 验证不通过 | |
| 274 | + if (!response.isSuccess()) { | |
| 275 | + throw exception(AUTH_REGISTER_CAPTCHA_CODE_ERROR, response.getRepMsg()); | |
| 276 | + } | |
| 294 | 277 | } |
| 278 | + | |
| 295 | 279 | } | ... | ... |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserService.java
| 1 | 1 | package cn.iocoder.yudao.module.system.service.user; |
| 2 | 2 | |
| 3 | 3 | import cn.hutool.core.collection.CollUtil; |
| 4 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | |
| 4 | 5 | import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; |
| 6 | +import cn.iocoder.yudao.module.system.controller.admin.auth.vo.AuthRegisterReqVO; | |
| 5 | 7 | import cn.iocoder.yudao.module.system.controller.admin.user.vo.profile.UserProfileUpdatePasswordReqVO; |
| 6 | 8 | import cn.iocoder.yudao.module.system.controller.admin.user.vo.profile.UserProfileUpdateReqVO; |
| 7 | -import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.*; | |
| 8 | -import cn.iocoder.yudao.framework.common.pojo.PageResult; | |
| 9 | +import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserImportExcelVO; | |
| 10 | +import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserImportRespVO; | |
| 11 | +import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserPageReqVO; | |
| 12 | +import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserSaveReqVO; | |
| 9 | 13 | import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; |
| 10 | - | |
| 11 | 14 | import jakarta.validation.Valid; |
| 15 | + | |
| 12 | 16 | import java.io.InputStream; |
| 13 | -import java.util.*; | |
| 17 | +import java.util.Collection; | |
| 18 | +import java.util.HashMap; | |
| 19 | +import java.util.List; | |
| 20 | +import java.util.Map; | |
| 14 | 21 | |
| 15 | 22 | /** |
| 16 | 23 | * 后台用户 Service 接口 |
| ... | ... | @@ -28,6 +35,14 @@ public interface AdminUserService { |
| 28 | 35 | Long createUser(@Valid UserSaveReqVO createReqVO); |
| 29 | 36 | |
| 30 | 37 | /** |
| 38 | + * 注册用户 | |
| 39 | + * | |
| 40 | + * @param registerReqVO 用户信息 | |
| 41 | + * @return 用户编号 | |
| 42 | + */ | |
| 43 | + Long registerUser(@Valid AuthRegisterReqVO registerReqVO); | |
| 44 | + | |
| 45 | + /** | |
| 31 | 46 | * 修改用户 |
| 32 | 47 | * |
| 33 | 48 | * @param updateReqVO 用户信息 | ... | ... |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserServiceImpl.java
| ... | ... | @@ -13,6 +13,7 @@ import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils; |
| 13 | 13 | import cn.iocoder.yudao.framework.datapermission.core.util.DataPermissionUtils; |
| 14 | 14 | import cn.iocoder.yudao.module.infra.api.config.ConfigApi; |
| 15 | 15 | import cn.iocoder.yudao.module.infra.api.file.FileApi; |
| 16 | +import cn.iocoder.yudao.module.system.controller.admin.auth.vo.AuthRegisterReqVO; | |
| 16 | 17 | import cn.iocoder.yudao.module.system.controller.admin.user.vo.profile.UserProfileUpdatePasswordReqVO; |
| 17 | 18 | import cn.iocoder.yudao.module.system.controller.admin.user.vo.profile.UserProfileUpdateReqVO; |
| 18 | 19 | import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserImportExcelVO; |
| ... | ... | @@ -116,6 +117,26 @@ public class AdminUserServiceImpl implements AdminUserService { |
| 116 | 117 | } |
| 117 | 118 | |
| 118 | 119 | @Override |
| 120 | + public Long registerUser(AuthRegisterReqVO registerReqVO) { | |
| 121 | + // 1.1 校验账户配合 | |
| 122 | + tenantService.handleTenantInfo(tenant -> { | |
| 123 | + long count = userMapper.selectCount(); | |
| 124 | + if (count >= tenant.getAccountCount()) { | |
| 125 | + throw exception(USER_COUNT_MAX, tenant.getAccountCount()); | |
| 126 | + } | |
| 127 | + }); | |
| 128 | + // 1.2 校验正确性 | |
| 129 | + validateUserForCreateOrUpdate(null, registerReqVO.getUsername(), null, null, null, null); | |
| 130 | + | |
| 131 | + // 2. 插入用户 | |
| 132 | + AdminUserDO user = BeanUtils.toBean(registerReqVO, AdminUserDO.class); | |
| 133 | + user.setStatus(CommonStatusEnum.ENABLE.getStatus()); // 默认开启 | |
| 134 | + user.setPassword(encodePassword(registerReqVO.getPassword())); // 加密密码 | |
| 135 | + userMapper.insert(user); | |
| 136 | + return user.getId(); | |
| 137 | + } | |
| 138 | + | |
| 139 | + @Override | |
| 119 | 140 | @Transactional(rollbackFor = Exception.class) |
| 120 | 141 | @LogRecord(type = SYSTEM_USER_TYPE, subType = SYSTEM_USER_UPDATE_SUB_TYPE, bizNo = "{{#updateReqVO.id}}", |
| 121 | 142 | success = SYSTEM_USER_UPDATE_SUCCESS) | ... | ... |