6.2 KiB
6.2 KiB
在上小节 中,我们已经完成了用户密码修改功能的开发。本小节中,回首掏,把登录接口中,还未完成的账号/密码登录逻辑补充完整。
添加错误状态码
首先,编辑认证服务中的 ResponseCodeEnum 全局枚举类,定义 3 个枚举值,如下,等会业务层需要做一些判断提示:
-
登录类型错误;
-
该用户不存在;
-
手机号或密码错误;
代码如下:
package com.quanxiaoha.xiaohashu.auth.enums;
import com.quanxiaoha.framework.common.exception.BaseExceptionInterface;
import lombok.AllArgsConstructor;
import lombok.Getter;
@Getter
@AllArgsConstructor
public enum ResponseCodeEnum implements BaseExceptionInterface {
// 省略...
LOGIN_TYPE_ERROR("AUTH-20002", "登录类型错误"),
USER_NOT_FOUND("AUTH-20003", "该用户不存在"),
PHONE_OR_PASSWORD_ERROR("AUTH-20004", "手机号或密码错误"),
;
// 异常码
private final String errorCode;
// 错误信息
private final String errorMessage;
}
完善账号/密码登录逻辑
package com.quanxiaoha.xiaohashu.auth.service.impl;
import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpUtil;
import com.alibaba.ttl.TransmittableThreadLocal;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import com.quanxiaoha.framework.biz.context.holder.LoginUserContextHolder;
import com.quanxiaoha.framework.common.enums.DeletedEnum;
import com.quanxiaoha.framework.common.enums.StatusEnum;
import com.quanxiaoha.framework.common.exception.BizException;
import com.quanxiaoha.framework.common.response.Response;
import com.quanxiaoha.framework.common.util.JsonUtils;
import com.quanxiaoha.xiaohashu.auth.constant.RedisKeyConstants;
import com.quanxiaoha.xiaohashu.auth.constant.RoleConstants;
import com.quanxiaoha.xiaohashu.auth.domain.dataobject.PermissionDO;
import com.quanxiaoha.xiaohashu.auth.domain.dataobject.RoleDO;
import com.quanxiaoha.xiaohashu.auth.domain.dataobject.UserDO;
import com.quanxiaoha.xiaohashu.auth.domain.dataobject.UserRoleDO;
import com.quanxiaoha.xiaohashu.auth.domain.mapper.RoleDOMapper;
import com.quanxiaoha.xiaohashu.auth.domain.mapper.UserDOMapper;
import com.quanxiaoha.xiaohashu.auth.domain.mapper.UserRoleDOMapper;
import com.quanxiaoha.xiaohashu.auth.enums.LoginTypeEnum;
import com.quanxiaoha.xiaohashu.auth.enums.ResponseCodeEnum;
import com.quanxiaoha.xiaohashu.auth.model.vo.user.UpdatePasswordReqVO;
import com.quanxiaoha.xiaohashu.auth.model.vo.user.UserLoginReqVO;
import com.quanxiaoha.xiaohashu.auth.service.UserService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;
import java.time.LocalDateTime;
import java.util.*;
/**
* @author: 犬小哈
* @date: 2024/4/7 15:41
* @version: v1.0.0
* @description: TODO
**/
@Service
@Slf4j
public class UserServiceImpl implements UserService {
// 省略...
@Resource
private PasswordEncoder passwordEncoder;
/**
* 登录与注册
*
* @param userLoginReqVO
* @return
*/
@Override
public Response<String> loginAndRegister(UserLoginReqVO userLoginReqVO) {
String phone = userLoginReqVO.getPhone();
Integer type = userLoginReqVO.getType();
LoginTypeEnum loginTypeEnum = LoginTypeEnum.valueOf(type);
// 登录类型错误
if (Objects.isNull(loginTypeEnum)) {
throw new BizException(ResponseCodeEnum.LOGIN_TYPE_ERROR);
}
Long userId = null;
// 判断登录类型
switch (loginTypeEnum) {
case VERIFICATION_CODE: // 验证码登录
// 省略...
break;
case PASSWORD: // 密码登录
String password = userLoginReqVO.getPassword();
// 根据手机号查询
UserDO userDO1 = userDOMapper.selectByPhone(phone);
// 判断该手机号是否注册
if (Objects.isNull(userDO1)) {
throw new BizException(ResponseCodeEnum.USER_NOT_FOUND);
}
// 拿到密文密码
String encodePassword = userDO1.getPassword();
// 匹配密码是否一致
boolean isPasswordCorrect = passwordEncoder.matches(password, encodePassword);
// 如果不正确,则抛出业务异常,提示用户名或者密码不正确
if (!isPasswordCorrect) {
throw new BizException(ResponseCodeEnum.PHONE_OR_PASSWORD_ERROR);
}
userId = userDO1.getId();
break;
default:
break;
}
// 省略...
// 返回 Token 令牌
return Response.success(tokenInfo.tokenValue);
}
// 省略...
}
解释一波代码逻辑:
- 判断登录类型是否正确,若不正确,则抛出业务异常;
- 账号/密码登录:
- 通过手机号,也就是账号来查询数据库;
- 若记录为空,说明登录的用户不存在,抛出对应的业务异常;
- 密码比对;
- 若不正确,则抛出业务异常,提示用户名或者密码不正确;
自测一波
逻辑补充完毕后,重启认证服务。自测一波登录接口,如下图所示:
入参如下:
{
"phone": "18019939111", // 手机号
"password": "123456", // 密码
"type": 2 // 2 代表账号密码登录
}
可以看到,通过账号/密码的方式登录,同样能够正确拿到登录 Token 令牌。