• Spring Boot + Mybatis Plus实现登录注册


    Spring Boot 实现登录注册

    1. 注册

    业务逻辑

    1. 客户端输入注册时需要的用户参数,比如:账户名、密码、确认密码、其他
    2. 服务端接收到客户端的请求参数进行校验,然后判断是否有误,有误的地方就将错误信息抛出
    3. 将密码进行加密之后存储到数据库中,切记不能以明文的方式存入
    4. 返回用户的id作为注册成功之后的返回信息

    具体实现 + 代码

    1. controller

      • 封装请求参数 UserRegisterRequest
      • 判断请求参数是否为空
      • 调用service的注册方法将请求参数传递给注册方法
      @PostMapping("/register")
          public BaseResponse<Long> userRegister(@RequestBody UserRegisterRequest userLoginRequest) {
              if(userLoginRequest == null) {
                  throw new BusinessException(ErrorCode.PARAMS_ERROR);
              }
              String userAccount = userLoginRequest.getUserAccount();
              String userPassword = userLoginRequest.getUserPassword();
              String checkPassword = userLoginRequest.getCheckPassword();
              if(StringUtils.isAnyBlank(userAccount, userPassword, checkPassword)) {
                  throw new BusinessException(ErrorCode.PARAMS_ERROR);
              }
              long result = userService.userRegister(userAccount, userPassword, checkPassword);
              return ResultUtils.success(result);
          }
      
    2. service

      • 判断请求参数对象是否为空 使用 StringUtils工具进行判断[需要下载org.apache.commons-lang3依赖]
      • 校验参数:
        • 账户名长度 < 3
        • 密码长度 < 4
        • 密码和确认密码是否相等
        • 用户名、密码、确认密码是否为空
      • 创建一个查询对象来确保账户是唯一的不能重复注册
      • 密码加密
      • 创建一个user对象,将用户信息存储到数据库中
      @Override
          public long userRegister(String userAccount, String userPassword, String checkPassword) {
              if(StringUtils.isAnyBlank(userAccount, userPassword, checkPassword)) {
                  throw new BusinessException(ErrorCode.PARAMS_ERROR);
              }
              if(userAccount.length() < 3) {
                  throw new BusinessException(ErrorCode.PARAMS_ERROR, "账户名长度太短");
              }
              if(userPassword.length() < 4) {
                  throw new BusinessException(ErrorCode.PARAMS_ERROR, "密码长度太短");
              }
              if(!userPassword.equals(checkPassword)) {
                  throw new BusinessException(ErrorCode.PARAMS_ERROR, "校验密码不相等");
              }
              // 加锁防止恶意注册操作
              synchronized (userAccount.intern()) {
                  QueryWrapper<User> queryWrapper = new QueryWrapper<>();
                  queryWrapper.eq("userAccount", userAccount);
                  Long count = this.baseMapper.selectCount(queryWrapper);
                  if (count > 0) {
                      throw new BusinessException(ErrorCode.PARAMS_ERROR, "该账号已注册");
                  }
                  String newUserPassword = DigestUtils.md5DigestAsHex((SLAT + userPassword).getBytes());
                  User user = new User();
                  user.setUserAccount(userAccount);
                  user.setUserPassword(newUserPassword);
                  boolean save = this.save(user);
                  if (!save) {
                      throw new BusinessException(ErrorCode.OPERATION_ERROR, "用户注册失败");
                  }
                  return user.getId();
              }
          }
      
    3. 测试

      image-20240606111153586

      通过观察服务器的响应,可以看到当前用户信息注册成功

      image-20240606111300500

      数据库中也能查询到该条用户数据

    2. 登录

    业务逻辑

    1. 用户输入登录时需要传递的参数:用户名、密码
    2. 服务器收到参数之后取出进行校验
    3. 创建一个queryWrapper进行查询,查询当前账户是否是唯一的,不允许未被注册就能登录的情况
    4. 将用户的登录信息存储到登录态中
    5. 返回脱敏后的用户信息

    具体实现 + 代码

    1. controller层

      • 封装一个用户登录请求的类,里面用于存入用户登陆时的请求参数

      • 取出所有参数判断是否为空

      • 调用service层中用户登录的方法

        @PostMapping("/login")
        public BaseResponse<UserLoginVO> userLogin(@RequestBody UserLoginRequest userLoginRequest, HttpServletRequest request) {
            if(userLoginRequest == null) {
                throw new BusinessException(ErrorCode.PARAMS_ERROR);
            }
            String userAccount = userLoginRequest.getUserAccount();
            String userPassword = userLoginRequest.getUserPassword();
            if(StringUtils.isAnyBlank(userAccount, userPassword)) {
                throw new BusinessException(ErrorCode.PARAMS_ERROR);
            }
            UserLoginVO result = userService.userLogin(userAccount, userPassword, request);
            return ResultUtils.success(result);
        }
        
    2. service层

      • 校验参数是否为空

      • 创建一个queryWrapper进行查询,是否有和当前账户和密码一致的数据库信息(注意这里的密码必须是加密之后的密码进行查询,否则会查不到)

      • 不存在的话就说明当前用户未注册

      • 将用户信息存储到登录态中

      • 返回脱敏之后的用户信息

        @Override
        public UserLoginVO userLogin(String userAccount, String userPassword, HttpServletRequest request) {
            // 1. 对参数进行校验 账户和密码是否为空
            if(StringUtils.isAnyBlank(userAccount, userPassword)) {
                throw new BusinessException(ErrorCode.PARAMS_ERROR);
            }
            // 2. 将用户的密码进行加密 有的话就登录成功    查询数据库中的账户是否存在   不存在就报错
            String md_userPassword = DigestUtils.md5DigestAsHex((SLAT + userPassword).getBytes());
            QueryWrapper<User> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("userAccount", userAccount);
            queryWrapper.eq("userPassword", md_userPassword);
            User user = this.baseMapper.selectOne(queryWrapper);
            if(user == null) {
                throw new BusinessException(ErrorCode.PARAMS_ERROR, "当前用户未注册");
            }
            // 3. 将用户信息存储到登录态中
            request.getSession().setAttribute(USER_LOGIN_STATE, user);
            // 3. 返回当前用户的所有信息(脱敏返回)
            return this.getUserLoginVO(user);
        }
        
    3. 测试

      输入前面我们注册的用户信息进行登录测试

      image-20240612185837959

      可以看出我们的登录功能是没有问题的,并且我们的request中也存储了用户的登录态信息

      image-20240612190111775

    总结:

    ​ 注册登录是一个软件的基本功能,主要需要注意里面service层中的校验逻辑,我这里的校验比较的简单,只是实现了基础的东西,如果更复杂的应用可能会有更加严格细致的校验。后续大家也可以考虑进行扩展,比如:将用户的登录信息存储存储到session中实现多个客户端共享一个用户的信息,不用重复登录;另外也可以考虑将用户的登录改为单设备登录,这适用于一些用户充值了vip之后只能在单设备登录的场景。

  • 相关阅读:
    [常用工具] Python视频解码库DeFFcode使用指北
    SpringSecurity初识及使用
    助力森林火情预警检测,基于YOLOv7-tiny、YOLOv7和YOLOv7x开发构建无人机航拍场景下的森林火情检测是别预警系统
    一个超强的机器学习库
    JUC学习笔记——进程与线程
    如何在linux系统上部署nginx
    彻底删除Ubuntu双系统(联想小新2022)
    小程序技术加速信创操作系统国产化替换
    python 格式化字符串的方法
    【JAVA数据结构】Stack栈的深度剖析
  • 原文地址:https://blog.csdn.net/qq_45993474/article/details/139634578