package edu.whut.smilepicturebackend.service.impl; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import edu.whut.smilepicturebackend.constant.UserConstant; import edu.whut.smilepicturebackend.exception.BusinessException; import edu.whut.smilepicturebackend.exception.ErrorCode; import edu.whut.smilepicturebackend.model.entity.User; import edu.whut.smilepicturebackend.model.enums.UserRoleEnum; import edu.whut.smilepicturebackend.model.vo.LoginUserVO; import edu.whut.smilepicturebackend.service.UserService; import edu.whut.smilepicturebackend.mapper.UserMapper; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.stereotype.Service; import javax.servlet.http.HttpServletRequest; /** * @author 张三 * @description 针对表【user(用户)】的数据库操作Service实现 * @createDate 2025-06-05 17:43:52 */ @Service @Slf4j @RequiredArgsConstructor public class UserServiceImpl extends ServiceImpl implements UserService{ private final BCryptPasswordEncoder passwordEncoder; /** * 用户注册 * * @param userAccount 用户账户 * @param userPassword 用户密码 * @param checkPassword 校验密码 * @return */ @Override public long userRegister(String userAccount, String userPassword, String checkPassword) { // 1. 校验参数 if (StrUtil.hasBlank(userAccount, userPassword, checkPassword)) { throw new BusinessException(ErrorCode.PARAMS_ERROR, "参数为空"); } if (userAccount.length() < 4) { throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户账号过短"); } if (userPassword.length() < 8 || checkPassword.length() < 8) { throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户密码过短"); } if (!userPassword.equals(checkPassword)) { throw new BusinessException(ErrorCode.PARAMS_ERROR, "两次输入的密码不一致"); } // 2. 检查用户账号是否和数据库中已有的重复 LambdaQueryWrapper lambda = Wrappers.lambdaQuery(); lambda.eq(User::getUserAccount, userAccount); long count = this.baseMapper.selectCount(lambda); if (count > 0) { throw new BusinessException(ErrorCode.PARAMS_ERROR, "账号重复"); } // 3. 密码一定要加密 String encryptPassword = getEncryptPassword(userPassword); // 4. 插入数据到数据库中 User user = new User(); user.setUserAccount(userAccount); user.setUserPassword(encryptPassword); user.setUserName("无名"); user.setUserRole(UserRoleEnum.USER.getValue()); boolean saveResult = this.save(user); if (!saveResult) { throw new BusinessException(ErrorCode.SYSTEM_ERROR, "注册失败,数据库错误"); } return user.getId(); } /** * 获取加密后的密码 * * @param userPassword 用户密码 * @return 加密后的密码 */ @Override public String getEncryptPassword(String userPassword) { return passwordEncoder.encode(userPassword); // // 加盐,混淆密码 // final String SALT = "smile12306"; // return DigestUtils.md5DigestAsHex((SALT + userPassword).getBytes()); } @Override public LoginUserVO userLogin(String userAccount, String userPassword, HttpServletRequest request) { // 1. 校验 if (StrUtil.hasBlank(userAccount, userPassword)) { throw new BusinessException(ErrorCode.PARAMS_ERROR, "参数为空"); } if (userAccount.length() < 4) { throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户账号错误"); } if (userPassword.length() < 8) { throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户密码错误"); } // 2. 对用户传递的密码进行加密 String encryptPassword = getEncryptPassword(userPassword); // 3. 查询数据库中的用户是否存在 LambdaQueryWrapper lambda = new LambdaQueryWrapper<>(); lambda .eq(User::getUserAccount, userAccount) .eq(User::getUserPassword, encryptPassword); User user = this.baseMapper.selectOne(lambda); // 不存在,抛异常 if (user == null) { log.info("user login failed, userAccount cannot match userPassword"); throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户不存在或者密码错误"); } // 4. 保存用户的登录态 request.getSession().setAttribute(UserConstant.USER_LOGIN_STATE, user); return this.getLoginUserVO(user); } /** * 获取脱敏类的用户信息 * * @param user 用户 * @return 脱敏后的用户信息 */ @Override public LoginUserVO getLoginUserVO(User user) { if (user == null) { return null; } LoginUserVO loginUserVO = new LoginUserVO(); BeanUtil.copyProperties(user, loginUserVO); return loginUserVO; } @Override public User getLoginUser(HttpServletRequest request) { // 判断是否已经登录 Object userObj = request.getSession().getAttribute(UserConstant.USER_LOGIN_STATE); User currentUser = (User) userObj; if (currentUser == null || currentUser.getId() == null) { throw new BusinessException(ErrorCode.NOT_LOGIN_ERROR); } // 从数据库中查询(追求性能的话可以注释,直接返回上述结果) Long userId = currentUser.getId(); currentUser = this.getById(userId); if (currentUser == null) { throw new BusinessException(ErrorCode.NOT_LOGIN_ERROR); } return currentUser; } /** * 退出登录 * * @param request * @return */ @Override public boolean userLogout(HttpServletRequest request) { // 判断是否已经登录 Object userObj = request.getSession().getAttribute(UserConstant.USER_LOGIN_STATE); if (userObj == null) { throw new BusinessException(ErrorCode.OPERATION_ERROR, "未登录"); } // 移除登录态 request.getSession().removeAttribute(UserConstant.USER_LOGIN_STATE); return true; } }