From 024d44cea1d06ecf12f694340223d5bdd3eafb07 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sun, 10 Oct 2021 22:52:20 +0800 Subject: [PATCH] 1. 增加前台用户的 token 刷新 2. 增加前台用户的 logout 退出 --- yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/enums/SysErrorCodeConstants.java | 5 +---- yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/auth/impl/SysAuthServiceImpl.java | 10 +++++----- yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/member/service/user/MbrUserService.java | 11 +++++++++++ yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/member/service/user/impl/MbrUserServiceImpl.java | 32 ++++++++++++++++++++++++++++++++ yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/SysAuthController.http | 16 +++++++++++++++- yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/SysAuthController.java | 18 ++++++++++-------- yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/MbrAuthLoginRespVO.java | 20 -------------------- yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/MbrAuthResetPasswordReqVO.java | 32 ++++++++++++++++++++++++++++++++ yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/MbrAuthSendSmsReqVO.java | 27 --------------------------- yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/MbrAuthSmsLoginReqVO.java | 38 -------------------------------------- yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/SysAuthLoginRespVO.java | 20 ++++++++++++++++++++ yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/SysAuthResetPasswordReqVO.java | 32 -------------------------------- yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/SysAuthSendSmsReqVO.java | 27 +++++++++++++++++++++++++++ yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/SysAuthSmsLoginReqVO.java | 33 +++++++++++++++++++++++++++++++++ yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/enums/SysErrorCodeConstants.java | 1 + yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/service/auth/SysAuthService.java | 11 +++++++++++ yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/service/auth/impl/SysAuthServiceImpl.java | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 17 files changed, 274 insertions(+), 137 deletions(-) delete mode 100644 yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/MbrAuthLoginRespVO.java create mode 100644 yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/MbrAuthResetPasswordReqVO.java delete mode 100644 yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/MbrAuthSendSmsReqVO.java delete mode 100644 yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/MbrAuthSmsLoginReqVO.java create mode 100644 yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/SysAuthLoginRespVO.java delete mode 100644 yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/SysAuthResetPasswordReqVO.java create mode 100644 yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/SysAuthSendSmsReqVO.java create mode 100644 yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/SysAuthSmsLoginReqVO.java diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/enums/SysErrorCodeConstants.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/enums/SysErrorCodeConstants.java index 72f6ac6..581f99b 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/enums/SysErrorCodeConstants.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/enums/SysErrorCodeConstants.java @@ -16,10 +16,7 @@ public interface SysErrorCodeConstants { ErrorCode AUTH_LOGIN_CAPTCHA_NOT_FOUND = new ErrorCode(1002000003, "验证码不存在"); ErrorCode AUTH_LOGIN_CAPTCHA_CODE_ERROR = new ErrorCode(1002000004, "验证码不正确"); ErrorCode AUTH_THIRD_LOGIN_NOT_BIND = new ErrorCode(1002000005, "未绑定账号,需要进行绑定"); - - // ========== TOKEN 模块 1002001000 ========== - ErrorCode TOKEN_EXPIRED = new ErrorCode(1002001000, "Token 已经过期"); - ErrorCode TOKEN_PARSE_FAIL = new ErrorCode(1002001001, "Token 解析失败"); + ErrorCode AUTH_TOKEN_EXPIRED = new ErrorCode(1002000006, "Token 已经过期"); // ========== 菜单模块 1002002000 ========== ErrorCode MENU_NAME_DUPLICATE = new ErrorCode(1002002000, "已经存在该名字的菜单"); diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/auth/impl/SysAuthServiceImpl.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/auth/impl/SysAuthServiceImpl.java index bfa5839..e7752f1 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/auth/impl/SysAuthServiceImpl.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/auth/impl/SysAuthServiceImpl.java @@ -255,15 +255,15 @@ public class SysAuthServiceImpl implements SysAuthService { } // 删除 session userSessionCoreService.deleteUserSession(token); - // 记录登出日子和 - this.createLogoutLog(loginUser.getUsername()); + // 记录登出日志 + this.createLogoutLog(loginUser.getId(), loginUser.getUsername()); } - private void createLogoutLog(String username) { - // TODO 芋艿:这里未设置 userId + private void createLogoutLog(Long userId, String username) { SysLoginLogCreateReqDTO reqDTO = new SysLoginLogCreateReqDTO(); reqDTO.setLogType(SysLoginLogTypeEnum.LOGOUT_SELF.getType()); reqDTO.setTraceId(TracerUtils.getTraceId()); + reqDTO.setUserId(userId); reqDTO.setUserType(UserTypeEnum.ADMIN.getValue()); reqDTO.setUsername(username); reqDTO.setUserAgent(ServletUtils.getUserAgent()); @@ -294,7 +294,7 @@ public class SysAuthServiceImpl implements SysAuthService { // 重新加载 SysUserDO 信息 SysUserDO user = userService.getUser(loginUser.getId()); if (user == null || CommonStatusEnum.DISABLE.getStatus().equals(user.getStatus())) { - throw exception(TOKEN_EXPIRED); // 校验 token 时,用户被禁用的情况下,也认为 token 过期,方便前端跳转到登录界面 + throw exception(AUTH_TOKEN_EXPIRED); // 校验 token 时,用户被禁用的情况下,也认为 token 过期,方便前端跳转到登录界面 } // 刷新 LoginUser 缓存 diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/member/service/user/MbrUserService.java b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/member/service/user/MbrUserService.java index 9a53d42..886fa01 100644 --- a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/member/service/user/MbrUserService.java +++ b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/member/service/user/MbrUserService.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.userserver.modules.member.service.user; +import cn.iocoder.yudao.framework.common.validation.Mobile; import cn.iocoder.yudao.userserver.modules.member.dal.dataobject.user.MbrUserDO; /** @@ -18,6 +19,16 @@ public interface MbrUserService { MbrUserDO getUserByMobile(String mobile); /** + * 基于手机号创建用户。 + * 如果用户已经存在,则直接进行返回 + * + * @param mobile 手机号 + * @param registerIp 注册 IP + * @return 用户对象 + */ + MbrUserDO createUserIfAbsent(@Mobile String mobile, String registerIp); + + /** * 更新用户的最后登陆信息 * * @param id 用户编号 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 ea15c41..51faf18 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 @@ -1,9 +1,14 @@ package cn.iocoder.yudao.userserver.modules.member.service.user.impl; +import cn.hutool.core.util.IdUtil; +import cn.hutool.core.util.RandomUtil; +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.userserver.modules.member.dal.dataobject.user.MbrUserDO; import cn.iocoder.yudao.userserver.modules.member.dal.mysql.user.MbrUserMapper; import cn.iocoder.yudao.userserver.modules.member.service.user.MbrUserService; import lombok.extern.slf4j.Slf4j; +import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; import javax.annotation.Resource; @@ -23,12 +28,39 @@ public class MbrUserServiceImpl implements MbrUserService { @Resource private MbrUserMapper userMapper; + @Resource + private PasswordEncoder passwordEncoder; + @Override public MbrUserDO getUserByMobile(String mobile) { return userMapper.selectByMobile(mobile); } @Override + public MbrUserDO createUserIfAbsent(String mobile, String registerIp) { + // 用户已经存在 + MbrUserDO user = userMapper.selectByMobile(mobile); + if (user != null) { + return user; + } + // 用户不存在,则进行创建 + return this.createUser(mobile, registerIp); + } + + private MbrUserDO createUser(String mobile, String registerIp) { + // 生成密码 + String password = IdUtil.fastSimpleUUID(); + // 插入用户 + MbrUserDO user = new MbrUserDO(); + user.setMobile(mobile); + user.setStatus(CommonStatusEnum.ENABLE.getStatus()); // 默认开启 + user.setPassword(passwordEncoder.encode(password)); // 加密密码 + user.setRegisterIp(registerIp); + userMapper.insert(user); + return user; + } + + @Override public void updateUserLogin(Long id, String loginIp) { userMapper.updateById(new MbrUserDO().setId(id).setLoginIp(loginIp).setLoginDate(new Date())); } diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/SysAuthController.http b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/SysAuthController.http index af42933..e02af92 100644 --- a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/SysAuthController.http +++ b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/SysAuthController.http @@ -12,6 +12,20 @@ POST {{userServerUrl}}/send-sms-code Content-Type: application/json { - "mobile": "15601691300", + "mobile": "15601691301", "scene": 1 } + +### 请求 /sms-login 接口 => 成功 +POST {{userServerUrl}}/sms-login +Content-Type: application/json + +{ + "mobile": "15601691301", + "code": 9999 +} + +### 请求 /logout 接口 => 成功 +POST {{userServerUrl}}/logout +Content-Type: application/json +Authorization: Bearer c1b76bdaf2c146c581caa4d7fd81ee66 diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/SysAuthController.java b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/SysAuthController.java index 18058bd..2b1fd61 100644 --- a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/SysAuthController.java +++ b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/SysAuthController.java @@ -33,28 +33,30 @@ public class SysAuthController { @PostMapping("/login") @ApiOperation("使用手机 + 密码登录") - public CommonResult login(@RequestBody @Valid SysAuthLoginReqVO reqVO) { + public CommonResult login(@RequestBody @Valid SysAuthLoginReqVO reqVO) { String token = authService.login(reqVO, getClientIP(), getUserAgent()); // 返回结果 - return success(MbrAuthLoginRespVO.builder().token(token).build()); + return success(SysAuthLoginRespVO.builder().token(token).build()); } @PostMapping("/sms-login") @ApiOperation("使用手机 + 验证码登录") - public CommonResult smsLogin(@RequestBody @Valid SysAuthLoginReqVO reqVO) { - return null; + public CommonResult smsLogin(@RequestBody @Valid SysAuthSmsLoginReqVO reqVO) { + String token = authService.smsLogin(reqVO, getClientIP(), getUserAgent()); + // 返回结果 + return success(SysAuthLoginRespVO.builder().token(token).build()); } @PostMapping("/send-sms-code") @ApiOperation("发送手机验证码") - public CommonResult sendSmsCode(@RequestBody @Valid MbrAuthSendSmsReqVO reqVO) { + public CommonResult sendSmsCode(@RequestBody @Valid SysAuthSendSmsReqVO reqVO) { smsCodeService.sendSmsCode(reqVO.getMobile(), reqVO.getScene(), getClientIP()); return success(true); } @PostMapping("/reset-password") @ApiOperation(value = "重置密码", notes = "用户忘记密码时使用") - public CommonResult resetPassword(@RequestBody @Valid SysAuthResetPasswordReqVO reqVO) { + public CommonResult resetPassword(@RequestBody @Valid MbrAuthResetPasswordReqVO reqVO) { return null; } @@ -74,7 +76,7 @@ public class SysAuthController { @PostMapping("/social-login") @ApiOperation("社交登录,使用 code 授权码") - public CommonResult socialLogin(@RequestBody @Valid MbrAuthSocialLoginReqVO reqVO) { + public CommonResult socialLogin(@RequestBody @Valid MbrAuthSocialLoginReqVO reqVO) { // String token = authService.socialLogin(reqVO, getClientIP(), getUserAgent()); // // 返回结果 // return success(MbrAuthLoginRespVO.builder().token(token).build()); @@ -83,7 +85,7 @@ public class SysAuthController { @PostMapping("/social-login2") @ApiOperation("社交登录,使用 code 授权码 + 账号密码") - public CommonResult socialLogin2(@RequestBody @Valid MbrAuthSocialLogin2ReqVO reqVO) { + public CommonResult socialLogin2(@RequestBody @Valid MbrAuthSocialLogin2ReqVO reqVO) { // String token = authService.socialLogin2(reqVO, getClientIP(), getUserAgent()); // // 返回结果 // return success(MbrAuthLoginRespVO.builder().token(token).build()); diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/MbrAuthLoginRespVO.java b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/MbrAuthLoginRespVO.java deleted file mode 100644 index 1601baa..0000000 --- a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/MbrAuthLoginRespVO.java +++ /dev/null @@ -1,20 +0,0 @@ -package cn.iocoder.yudao.userserver.modules.system.controller.auth.vo; - -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; - -@ApiModel("手机密码登录 Response VO") -@Data -@NoArgsConstructor -@AllArgsConstructor -@Builder -public class MbrAuthLoginRespVO { - - @ApiModelProperty(value = "token", required = true, example = "yudaoyuanma") - private String token; - -} diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/MbrAuthResetPasswordReqVO.java b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/MbrAuthResetPasswordReqVO.java new file mode 100644 index 0000000..3b3556f --- /dev/null +++ b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/MbrAuthResetPasswordReqVO.java @@ -0,0 +1,32 @@ +package cn.iocoder.yudao.userserver.modules.system.controller.auth.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.hibernate.validator.constraints.Length; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.Pattern; + +@ApiModel("重置密码 Request VO") +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class MbrAuthResetPasswordReqVO { + + @ApiModelProperty(value = "新密码", required = true, example = "buzhidao") + @NotEmpty(message = "新密码不能为空") + @Length(min = 4, max = 16, message = "密码长度为 4-16 位") + private String password; + + @ApiModelProperty(value = "手机验证码", required = true, example = "1024") + @NotEmpty(message = "手机验证码不能为空") + @Length(min = 4, max = 6, message = "手机验证码长度为 4-6 位") + @Pattern(regexp = "^[0-9]+$", message = "手机验证码必须都是数字") + private String code; + +} diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/MbrAuthSendSmsReqVO.java b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/MbrAuthSendSmsReqVO.java deleted file mode 100644 index 6ce41ca..0000000 --- a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/MbrAuthSendSmsReqVO.java +++ /dev/null @@ -1,27 +0,0 @@ -package cn.iocoder.yudao.userserver.modules.system.controller.auth.vo; - -import cn.iocoder.yudao.framework.common.validation.InEnum; -import cn.iocoder.yudao.framework.common.validation.Mobile; -import cn.iocoder.yudao.userserver.modules.system.enums.sms.SysSmsSceneEnum; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; -import lombok.Data; -import lombok.experimental.Accessors; - -import javax.validation.constraints.NotNull; - -@ApiModel("发送手机验证码 Response VO") -@Data -@Accessors(chain = true) -public class MbrAuthSendSmsReqVO { - - @ApiModelProperty(value = "手机号", example = "15601691234") - @Mobile - private String mobile; - - @ApiModelProperty(value = "发送场景", example = "1", notes = "对应 MbrSmsSceneEnum 枚举") - @NotNull(message = "发送场景不能为空") - @InEnum(SysSmsSceneEnum.class) - private Integer scene; - -} diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/MbrAuthSmsLoginReqVO.java b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/MbrAuthSmsLoginReqVO.java deleted file mode 100644 index 56b4e50..0000000 --- a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/MbrAuthSmsLoginReqVO.java +++ /dev/null @@ -1,38 +0,0 @@ -package cn.iocoder.yudao.userserver.modules.system.controller.auth.vo; - -import cn.iocoder.yudao.framework.common.validation.Mobile; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; -import org.hibernate.validator.constraints.Length; - -import javax.validation.constraints.NotEmpty; -import javax.validation.constraints.Pattern; - -@ApiModel("手机 + 验证码登录 Request VO") -@Data -@NoArgsConstructor -@AllArgsConstructor -@Builder -public class MbrAuthSmsLoginReqVO { - - @ApiModelProperty(value = "手机号", required = true, example = "15601691300") - @NotEmpty(message = "手机号不能为空") - @Mobile - private String mobile; - - @ApiModelProperty(value = "密码", required = true, example = "buzhidao") - @NotEmpty(message = "密码不能为空") - @Length(min = 4, max = 16, message = "密码长度为 4-16 位") - private String password; - - @ApiModelProperty(value = "手机验证码", required = true, example = "1024") - @NotEmpty(message = "手机验证码不能为空") - @Length(min = 4, max = 6, message = "手机验证码长度为 4-6 位") - @Pattern(regexp = "^[0-9]+$", message = "手机验证码必须都是数字") - private String code; - -} diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/SysAuthLoginRespVO.java b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/SysAuthLoginRespVO.java new file mode 100644 index 0000000..95c69c7 --- /dev/null +++ b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/SysAuthLoginRespVO.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.userserver.modules.system.controller.auth.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@ApiModel("手机密码登录 Response VO") +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class SysAuthLoginRespVO { + + @ApiModelProperty(value = "token", required = true, example = "yudaoyuanma") + private String token; + +} diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/SysAuthResetPasswordReqVO.java b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/SysAuthResetPasswordReqVO.java deleted file mode 100644 index 01e438c..0000000 --- a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/SysAuthResetPasswordReqVO.java +++ /dev/null @@ -1,32 +0,0 @@ -package cn.iocoder.yudao.userserver.modules.system.controller.auth.vo; - -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; -import org.hibernate.validator.constraints.Length; - -import javax.validation.constraints.NotEmpty; -import javax.validation.constraints.Pattern; - -@ApiModel("重置密码 Request VO") -@Data -@NoArgsConstructor -@AllArgsConstructor -@Builder -public class SysAuthResetPasswordReqVO { - - @ApiModelProperty(value = "新密码", required = true, example = "buzhidao") - @NotEmpty(message = "新密码不能为空") - @Length(min = 4, max = 16, message = "密码长度为 4-16 位") - private String password; - - @ApiModelProperty(value = "手机验证码", required = true, example = "1024") - @NotEmpty(message = "手机验证码不能为空") - @Length(min = 4, max = 6, message = "手机验证码长度为 4-6 位") - @Pattern(regexp = "^[0-9]+$", message = "手机验证码必须都是数字") - private String code; - -} diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/SysAuthSendSmsReqVO.java b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/SysAuthSendSmsReqVO.java new file mode 100644 index 0000000..d8c6c98 --- /dev/null +++ b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/SysAuthSendSmsReqVO.java @@ -0,0 +1,27 @@ +package cn.iocoder.yudao.userserver.modules.system.controller.auth.vo; + +import cn.iocoder.yudao.framework.common.validation.InEnum; +import cn.iocoder.yudao.framework.common.validation.Mobile; +import cn.iocoder.yudao.userserver.modules.system.enums.sms.SysSmsSceneEnum; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.experimental.Accessors; + +import javax.validation.constraints.NotNull; + +@ApiModel("发送手机验证码 Response VO") +@Data +@Accessors(chain = true) +public class SysAuthSendSmsReqVO { + + @ApiModelProperty(value = "手机号", example = "15601691234") + @Mobile + private String mobile; + + @ApiModelProperty(value = "发送场景", example = "1", notes = "对应 MbrSmsSceneEnum 枚举") + @NotNull(message = "发送场景不能为空") + @InEnum(SysSmsSceneEnum.class) + private Integer scene; + +} diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/SysAuthSmsLoginReqVO.java b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/SysAuthSmsLoginReqVO.java new file mode 100644 index 0000000..a7b36bb --- /dev/null +++ b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/SysAuthSmsLoginReqVO.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.userserver.modules.system.controller.auth.vo; + +import cn.iocoder.yudao.framework.common.validation.Mobile; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.hibernate.validator.constraints.Length; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.Pattern; + +@ApiModel("手机 + 验证码登录 Request VO") +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class SysAuthSmsLoginReqVO { + + @ApiModelProperty(value = "手机号", required = true, example = "15601691300") + @NotEmpty(message = "手机号不能为空") + @Mobile + private String mobile; + + @ApiModelProperty(value = "手机验证码", required = true, example = "1024") + @NotEmpty(message = "手机验证码不能为空") + @Length(min = 4, max = 6, message = "手机验证码长度为 4-6 位") + @Pattern(regexp = "^[0-9]+$", message = "手机验证码必须都是数字") + private String code; + +} 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 3abcab5..e5f4ac6 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 @@ -13,6 +13,7 @@ public interface SysErrorCodeConstants { ErrorCode AUTH_LOGIN_BAD_CREDENTIALS = new ErrorCode(1005000000, "登录失败,账号密码不正确"); ErrorCode AUTH_LOGIN_USER_DISABLED = new ErrorCode(1005000001, "登录失败,账号被禁用"); ErrorCode AUTH_LOGIN_FAIL_UNKNOWN = new ErrorCode(1005000002, "登录失败"); // 登录失败的兜底,未知原因 + ErrorCode AUTH_TOKEN_EXPIRED = new ErrorCode(1005000003, "Token 已经过期"); // ========== SMS CODE 模块 1005001000 ========== ErrorCode USER_SMS_CODE_NOT_FOUND = new ErrorCode(1005001000, "验证码不存在"); diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/service/auth/SysAuthService.java b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/service/auth/SysAuthService.java index b560f9d..b35d1c2 100644 --- a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/service/auth/SysAuthService.java +++ b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/service/auth/SysAuthService.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.userserver.modules.system.service.auth; import cn.iocoder.yudao.framework.security.core.service.SecurityAuthFrameworkService; import cn.iocoder.yudao.userserver.modules.system.controller.auth.vo.SysAuthLoginReqVO; +import cn.iocoder.yudao.userserver.modules.system.controller.auth.vo.SysAuthSmsLoginReqVO; import javax.validation.Valid; @@ -24,4 +25,14 @@ public interface SysAuthService extends SecurityAuthFrameworkService { */ String login(@Valid SysAuthLoginReqVO reqVO, String userIp, String userAgent); + /** + * 手机 + 验证码登陆 + * + * @param reqVO 登陆信息 + * @param userIp 用户 IP + * @param userAgent 用户 UA + * @return 身份令牌,使用 JWT 方式 + */ + String smsLogin(@Valid SysAuthSmsLoginReqVO reqVO, String userIp, String userAgent); + } diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/service/auth/impl/SysAuthServiceImpl.java b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/service/auth/impl/SysAuthServiceImpl.java index 0c84cfc..1baaa24 100644 --- a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/service/auth/impl/SysAuthServiceImpl.java +++ b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/service/auth/impl/SysAuthServiceImpl.java @@ -1,18 +1,24 @@ package cn.iocoder.yudao.userserver.modules.system.service.auth.impl; +import cn.hutool.core.lang.Assert; import cn.iocoder.yudao.coreservice.modules.system.service.auth.SysUserSessionCoreService; import cn.iocoder.yudao.coreservice.modules.system.service.logger.SysLoginLogCoreService; import cn.iocoder.yudao.coreservice.modules.system.service.logger.dto.SysLoginLogCreateReqDTO; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils; import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; import cn.iocoder.yudao.framework.security.core.LoginUser; import cn.iocoder.yudao.userserver.modules.system.controller.auth.vo.SysAuthLoginReqVO; +import cn.iocoder.yudao.userserver.modules.system.controller.auth.vo.SysAuthSmsLoginReqVO; import cn.iocoder.yudao.userserver.modules.system.convert.auth.SysAuthConvert; import cn.iocoder.yudao.userserver.modules.member.dal.dataobject.user.MbrUserDO; +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.member.service.user.MbrUserService; import cn.iocoder.yudao.coreservice.modules.system.enums.logger.SysLoginLogTypeEnum; import cn.iocoder.yudao.coreservice.modules.system.enums.logger.SysLoginResultEnum; +import cn.iocoder.yudao.userserver.modules.system.service.sms.SysSmsCodeService; import lombok.extern.slf4j.Slf4j; import org.springframework.context.annotation.Lazy; import org.springframework.security.authentication.AuthenticationManager; @@ -24,7 +30,7 @@ import org.springframework.security.core.AuthenticationException; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.stereotype.Service; -import org.springframework.util.Assert; +import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; import java.util.Objects; @@ -48,6 +54,8 @@ public class SysAuthServiceImpl implements SysAuthService { @Resource private MbrUserService userService; @Resource + private SysSmsCodeService smsCodeService; + @Resource private SysLoginLogCoreService loginLogCoreService; @Resource private SysUserSessionCoreService userSessionCoreService; @@ -72,6 +80,25 @@ public class SysAuthServiceImpl implements SysAuthService { return userSessionCoreService.createUserSession(loginUser, userIp, userAgent); } + @Override + @Transactional + public String smsLogin(SysAuthSmsLoginReqVO reqVO, String userIp, String userAgent) { + // 校验验证码 + smsCodeService.useSmsCode(reqVO.getMobile(), SysSmsSceneEnum.LOGIN_BY_SMS.getScene(), + reqVO.getCode(), userIp); + + // 获得获得注册用户 + MbrUserDO user = userService.createUserIfAbsent(reqVO.getMobile(), userIp); + Assert.notNull(user, "获取用户失败,结果为空"); + + // 执行登陆 + this.createLoginLog(user.getMobile(), SysLoginLogTypeEnum.LOGIN_SMS, SysLoginResultEnum.SUCCESS); + LoginUser loginUser = SysAuthConvert.INSTANCE.convert(user); + + // 缓存登录用户到 Redis 中,返回 sessionId 编号 + return userSessionCoreService.createUserSession(loginUser, userIp, userAgent); + } + private LoginUser login0(String username, String password) { final SysLoginLogTypeEnum logTypeEnum = SysLoginLogTypeEnum.LOGIN_USERNAME; // 用户验证 @@ -120,7 +147,31 @@ public class SysAuthServiceImpl implements SysAuthService { @Override public LoginUser verifyTokenAndRefresh(String token) { - return null; + // 获得 LoginUser + LoginUser loginUser = userSessionCoreService.getLoginUser(token); + if (loginUser == null) { + return null; + } + // 刷新 LoginUser 缓存 + this.refreshLoginUserCache(token, loginUser); + return loginUser; + } + + private void refreshLoginUserCache(String token, LoginUser loginUser) { + // 每 1/3 的 Session 超时时间,刷新 LoginUser 缓存 + if (System.currentTimeMillis() - loginUser.getUpdateTime().getTime() < + userSessionCoreService.getSessionTimeoutMillis() / 3) { + return; + } + + // 重新加载 MbrUserDO 信息 + MbrUserDO user = userService.getUser(loginUser.getId()); + if (user == null || CommonStatusEnum.DISABLE.getStatus().equals(user.getStatus())) { + throw exception(AUTH_TOKEN_EXPIRED); // 校验 token 时,用户被禁用的情况下,也认为 token 过期,方便前端跳转到登录界面 + } + + // 刷新 LoginUser 缓存 + userSessionCoreService.refreshUserSession(token, loginUser); } @Override @@ -130,6 +181,8 @@ public class SysAuthServiceImpl implements SysAuthService { if (user == null) { throw new UsernameNotFoundException(String.valueOf(userId)); } + + // 执行登陆 this.createLoginLog(user.getMobile(), SysLoginLogTypeEnum.LOGIN_MOCK, SysLoginResultEnum.SUCCESS); // 创建 LoginUser 对象 @@ -138,7 +191,28 @@ public class SysAuthServiceImpl implements SysAuthService { @Override public void logout(String token) { + // 查询用户信息 + LoginUser loginUser = userSessionCoreService.getLoginUser(token); + if (loginUser == null) { + return; + } + // 删除 session + userSessionCoreService.deleteUserSession(token); + // 记录登出日志 + this.createLogoutLog(loginUser.getId(), loginUser.getUsername()); + } + private void createLogoutLog(Long userId, String username) { + SysLoginLogCreateReqDTO reqDTO = new SysLoginLogCreateReqDTO(); + reqDTO.setLogType(SysLoginLogTypeEnum.LOGOUT_SELF.getType()); + reqDTO.setTraceId(TracerUtils.getTraceId()); + reqDTO.setUserId(userId); + reqDTO.setUserType(UserTypeEnum.MEMBER.getValue()); + reqDTO.setUsername(username); + reqDTO.setUserAgent(ServletUtils.getUserAgent()); + reqDTO.setUserIp(ServletUtils.getClientIP()); + reqDTO.setResult(SysLoginResultEnum.SUCCESS.getResult()); + loginLogCoreService.createLoginLog(reqDTO); } } -- libgit2 0.21.4