spring boot3登录开发-3(2短信验证登录/注册逻辑实现)

news2024/11/26 14:32:34

 

⛰️个人主页:     蒾酒

🔥系列专栏:《spring boot实战》

🌊山高路远,行路漫漫,终有归途


目录

写在前面

上文衔接

内容简介

功能分析

短信验证登录实现

1.创建交互对象

用户短信登录/注册DTO

创建用户登录VO

2.创建自定义业务异常

创建验证码错误异常

创建用户被封禁异常

 创建用户注册失败异常

3.登录注册业务逻辑实现

4.测试接口

调用短信验证码发送接口

调用短信验证登录接口

写在最后


写在前面

本文介绍了springboot开发后端服务中,短信验证码登录功能的设计与实现,坚持看完相信对你有帮助。

同时欢迎订阅springboot系列专栏,持续分享spring boot的使用经验。

上文衔接

本文衔接上文,可以看一下:

spring boot3登录开发-2(2短信验证码接口实现)-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/qq_62262918/article/details/136888851?spm=1001.2014.3001.5501

用户表设计如下:

create table user
(
    id           bigint auto_increment comment '主键'
        primary key,
    user_name    varchar(32)                            null comment '用户昵称',
    password     varchar(256)                           null comment '密码',
    user_account varchar(64)                            null comment '账号',
    user_role    varchar(256) default 'user'            null comment '用户角色:user / admin',
    avatar       varchar(1024)                          null comment '头像',
    create_time  datetime     default (now())           null comment '创建时间',
    update_time  datetime     default CURRENT_TIMESTAMP null comment '更新时间',
    is_delete    tinyint(1)   default 0                 null comment '逻辑删除:1删除/0存在',
    gender       tinyint(1)                             null comment '性别',
    status       tinyint(1)   default 1                 not null comment '状态:1正常0禁用',
    phone        varchar(11)                            null comment '手机号'
)
    comment '用户表';

内容简介

上文我们已经实现了短信验证码的发送接口,本文我们来实现这个短信验证登录/注册逻辑。

功能分析

  • 手机号是新手机号则先注册,注册完执行登录
  • 已经注册过的手机号,直接执行登录

短信验证登录实现

1.创建交互对象

用户短信登录/注册DTO

import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Pattern;
import lombok.Data;

/**
 * @author mijiupro
 */
@Data
public class UserSmsLoginDTO {

    @NotBlank( message = "手机号不能为空")
    @Pattern(regexp = "^1[3456789]\\d{9}$", message = "手机号格式不正确")
    private String phone;//手机号

    @NotBlank( message = "验证码不能为空")
    private String captcha;//验证码
}

创建用户登录VO

import lombok.Builder;
import lombok.Data;
 
import java.io.Serializable;
 
 
/**
 * @author mijiupro
 */
@Data
@Builder
public class UserLoginVO implements Serializable {
    private String token;//令牌
    private String userName;//用户名
    private String avatar;//头像
}

2.创建自定义业务异常

说白了就是登录代码可能会判断账号是否存在,密码是否正确,当账号不存在或密码错误需要返回对应提示信息,这种类似情况多了你的代码就会很多if-return,代码就会很难看;那么通过自定义异常去到异常处理的方法里面写对应返回提示以及其他逻辑,这样直接抛出对应异常AOP拦截到该异常走对应异常处理逻辑即可。(一句话概括就是:把处理特殊业务异常情况的代码逻辑抽取出来放到别的类里面写,可以使代码更加清晰和可维护)

创建验证码错误异常

import com.mijiu.commom.enumerate.ResultEnum;
import lombok.Getter;
 
/**
 * @author mijiupro
 */
@Getter
public class CaptchaErrorException extends RuntimeException {
    private final ResultEnum resultEnum;//返回提示信息枚举(code,message)
 
    public CaptchaErrorException(ResultEnum resultEnum) {
        this.resultEnum = resultEnum;
    }
}

创建用户被封禁异常

import com.mijiu.commom.enumerate.ResultEnum;
import lombok.Getter;
 
/**
 * @author mijiupro
 */
@Getter
public class AccountForbiddenException extends RuntimeException {
    private final ResultEnum resultEnum;
 
    public AccountForbiddenException(ResultEnum resultEnum) {
        this.resultEnum = resultEnum;
    }
}

 创建用户注册失败异常

import com.mijiu.commom.enumerate.ResultEnum;
import lombok.Getter;

/**
 * @author mijiupro
 */
@Getter
public class AccountRegisterFailException extends RuntimeException {
    private final ResultEnum resultEnum;//返回提示信息枚举(code,message)

    public AccountRegisterFailException(ResultEnum resultEnum) {
        this.resultEnum = resultEnum;
    }
}

3.登录注册业务逻辑实现

import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.mijiu.commom.enumerate.ResultEnum;
import com.mijiu.commom.exception.*;
import com.mijiu.commom.model.dto.UserLoginDTO;
import com.mijiu.commom.model.dto.UserSmsLoginDTO;
import com.mijiu.commom.model.vo.UserLoginVO;
import com.mijiu.commom.util.JwtUtils;
import com.mijiu.entity.User;
import com.mijiu.mapper.UserMapper;
import com.mijiu.service.UserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;


import java.util.Map;
import java.util.Objects;

/**
 * <p>
 * 用户表 服务实现类
 * </p>
 *
 * @author 蒾酒
 * @since 2024-02-03
 */
@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    private final UserMapper userMapper;
    private final JwtUtils jwtUtils;
    private final StringRedisTemplate stringRedisTemplate;

    public UserServiceImpl(UserMapper userMapper, JwtUtils jwtUtils, StringRedisTemplate stringRedisTemplate) {
        this.userMapper = userMapper;
        this.jwtUtils = jwtUtils;
        this.stringRedisTemplate = stringRedisTemplate;
    }

 

    @Override
    public UserLoginVO SmsLogin(UserSmsLoginDTO userSmsLoginDTO) {
        // 校验验证码是否存在
        HashOperations<String, String, String> hashOps = stringRedisTemplate.opsForHash();
        String captcha = hashOps.get("login:sms:captcha:" + userSmsLoginDTO.getPhone(), "captcha");

        if (StringUtils.isEmpty(captcha)) {
            log.error("手机号 {} 的验证码不存在或已过期", userSmsLoginDTO.getPhone());
            throw new CaptchaErrorException(ResultEnum.USER_CAPTCHA_NOT_EXIST);
        }

        // 查询用户是否已注册
        User loginUser = new LambdaQueryChainWrapper<>(userMapper).eq(User::getPhone, userSmsLoginDTO.getPhone()).one();

        // 如果未注册则进行注册
        if (Objects.isNull(loginUser)) {
            loginUser = register(userSmsLoginDTO.getPhone());
        }

        // 校验验证码是否正确
        if (!userSmsLoginDTO.getCaptcha().equals(captcha)) {
            log.error("手机号 {} 的验证码错误", userSmsLoginDTO.getPhone());
            throw new CaptchaErrorException(ResultEnum.AUTH_CODE_ERROR);
        }
        //判断用户是否被禁用
        if (!loginUser.getStatus()) {
            throw new AccountForbiddenException(ResultEnum.USER_ACCOUNT_FORBIDDEN);
        }
        log.info("手机号 {} 用户登录成功", userSmsLoginDTO.getPhone());

        return UserLoginVO.builder()
                .token(jwtUtils.generateToken(Map.of("userId", loginUser.getId()), "user"))
                .userName(loginUser.getUserName())
                .build();
    }

    private User register(String phone) {
        User user = new User();
        user.setPhone(phone);
        user.setUserName(phone);
        user.setStatus(true);
        if (userMapper.insert(user) < 1) {
            log.error("手机号 {} 用户注册失败!", phone);
            throw new AccountRegisterFailException(ResultEnum.USER_REGISTER_FAIL);
        }
        log.info("手机号 {} 用户注册成功", phone);
        return user;
    }
}

4.测试接口

使用swagger3进行测试

Spring Boot3整合knife4j(swagger3)_springboot3 knife4j-CSDN博客文章浏览阅读2.3k次,点赞39次,收藏54次。Knife4j · 集Swagger2及OpenAPI3为一体的增强解决方案. | Knife4j (xiaominfo.com)作者的使用的spring boot 3.2.2为当前最新版,所以依赖导入最新的knife4j 4.4.0。3.1 增强模式 | Knife4j (xiaominfo.com)好一个spring boot项目且版本为3X,项目可正常启动。快速开始 | Knife4j (xiaominfo.com)接下来配置以下接口文档的作者等信息。@Tag注解:标记接口类别。_springboot3 knife4jhttps://blog.csdn.net/qq_62262918/article/details/135761392?spm=1001.2014.3001.5502

调用短信验证码发送接口

调用短信验证登录接口

第一次登录所以也就自动注册成功了。

写在最后

springboot实现短信验证登录注册到这里就结束了,本文介绍了一种通用的短信验证登录实现方式,代码逻辑清晰。任何问题评论区或私信讨论,欢迎指正。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1563195.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

harmonyOS的客户端存贮

什么是客户端存贮 在harmonyOS中,客户端存贮是指将数据存贮在本地设备以供应用程序使用; 注: 和feaureAblity搭配使用,content上下文的获取依赖该API如下: // 引入: import featureAbility from ohos.ability.featureAbility;// 使用: let content featureAbility.getConten…

Git Fork后的仓库内容和原仓库保持一致

Git Fork后的仓库内容和原仓库保持一致 ①Fork原仓库内容到自己仓库 ②将项目内容下载到本地 ③使用git命令获取原仓库内容&#xff0c;将原仓库的最新内容合并到自己的分支上并推送 下面从第三步开始演示~ 这里以码云上的若依项目为演示项目 ③使用git命令获取原仓库内容 …

NLP重要知识点:预训练模型【核心且详细】

本资料是NLP核心知识点的ppt!!!【文章较长,建议收藏】 本节课我们学习预训练模型。 前言 我们在学习词向量的时候,应该知道了多个产生词向量的方法,包括基于矩阵(词-词共现矩阵)分解的方法、基于语言模型(word2vec)的方法、以及结合二者优点的Glove模型等其他产生词…

10kV配电室在线监控改造技术方案

摘要&#xff1a;目前&#xff0c;我国经济高速发展&#xff0c;社会在不断进步&#xff0c;国家加大了农村低压配电网络改造升级投入&#xff0c;低压配电网供电可靠性及供电质量得到明显提升&#xff0c;但低压配电网络自动化运维水平及农村电网用电安全尚处于较低水平。低压…

opejdk11 java 启动流程 java main方法怎么被jvm执行

java启动过程 java main方法怎么被jvm执行 java main方法是怎么被jvm调用的 1、jvm main入口 2、执行JLI_Launch方法 3、执行JVMInit方法 4、执行ContinueInNewThread方法 5、执行CallJavaMainInNewThread方法 6、创建线程执行ThreadJavaMain方法 7、执行ThreadJavaMain方法…

【算法刷题day14】二叉树理论基础、递归遍历、迭代遍历、统一迭代

二叉树理论基础 题目分类 二叉树的种类 无数值两种&#xff1a;满二叉树 和 完全二叉树 有数值&#xff1a;二叉搜索树 1.若它的左子树不空&#xff0c;则左子树上所有结点的值均小于它的根结点的值; 2.若它的右子树不空&#xff0c;则右子树上所有结点的值均大于它的根结点…

14.Python网络通信

本章讲解如何通过Python访问互联网上的资源&#xff0c;这也是网络爬虫技 术的基础。 1 基本的网络知识 程序员在进行网络编程前&#xff0c;需要掌握基本的网络知识&#xff0c;本节会介绍 这些内容。 1.1 TCP/IP 在网络通信中会用到一些相关协议&#xff0c;其中&#xf…

备考ICA----Istio实验16---HTTP流量授权

备考ICA----Istio实验16—HTTP流量授权 1. 环境准备 kubectl apply -f istio/samples/bookinfo/platform/kube/bookinfo.yaml kubectl apply -f istio/samples/bookinfo/networking/bookinfo-gateway.yaml访问测试 curl -I http://192.168.126.220/productpage2. 开启mtls …

python对接百度云车牌识别

注册百度智能云&#xff0c;选择产品服务。 https://console.bce.baidu.com/ 每天赠送200次&#xff0c;做开发测试足够了。 在应用列表复制 AppID , API Key ,Secret Key 备用。 SDK下载地址 https://ai.baidu.com/sdk#ocr 下载SDK文件&#xff0c;解压&#xff0c;…

面试 五

一、设计模式 1、工厂模式 工程模式&#xff1a;在javascript中&#xff0c;工程模式的表现形式就是 一调用即可返回新对象的函数。 // 工厂模式 function person (name, age) {return { name, age} } const person1 person("tom", 18) const person2 person(&q…

Google DeepMind 大语言模型中的长形态事实性

&#x1f349; CSDN 叶庭云&#xff1a;https://yetingyun.blog.csdn.net/ 论文标题&#xff1a;Long-form factuality in large language models 论文链接&#xff1a;https://arxiv.org/abs/2403.18802 论文的关键信息总结如下&#xff1a; 研究问题是什么&#xff1f;论文…

9proxy—数据采集工具全面测评

9Proxy数据采集工具Unlock the web with 9Proxy, the top residential proxy provider. Get unlimited bandwidth, affordable prices, and secure HTTPS and Socks5 configurations.https://9proxy.com/?utm_sourceblog&utm_mediumcsdn&utm_campaignyan 前言 在当今数…

【智能算法】蜣螂优化算法(DBO)原理及实现

目录 1.背景2.算法原理2.1算法思想2.2算法过程 3.结果展示4.参考文献 1.背景 2022年&#xff0c;Xue等人受到自然界中蜣螂生存行为启发&#xff0c;提出了蜣螂优化算法&#xff08;Dung beetle optimizer, DBO&#xff09;。 2.算法原理 2.1算法思想 DBO模拟了自然界蜣螂种…

泛域名站群,泛域名程序

泛域名站群是一种利用大量类似的泛域名来建立多个网站&#xff0c;并通过这些网站链接到主网站&#xff0c;以提升主网站的排名和流量的策略。泛域名站群通常包含大量的子域名&#xff0c;这些子域名指向不同的页面&#xff0c;但它们的内容大部分是重复或相似的&#xff0c;目…

机器学习KNN最邻近分类算法

文章目录 1、KNN算法简介2、KNN算法实现3、调用scikit-learn库中KNN算法4、使用scikit-learn库生成数据集5、自定义函数划分数据集6、使用scikit-learn库划分数据集7、使用scikit-learn库对鸢尾花数据集进行分类 1、KNN算法简介 KNN (K-Nearest Neighbor) 最邻近分类算法&#…

4款在线网页原型图设计软件推荐

与桌面端相比&#xff0c;在线网页原型设计软件的使用具有优势&#xff0c;因为在线网页原型设计软件在整个使用过程中不需要安装&#xff0c;在线网页原型设计软件在任何地方都没有限制。更重要的是&#xff0c;无论是现在使用的 Linux&#xff0c;在线网页原型设计软件在操作…

【THM】Burp Suite:Other Modules(其他模块)-初级渗透测试

介绍 除了广泛认可的Repeater和Intruder房间之外,Burp Suite 还包含几个鲜为人知的模块。这些将成为这个房间探索的重点。 重点将放在解码器、比较器、排序器和组织器工具上。它们促进了编码文本的操作,支持数据集的比较,允许分析捕获的令牌内的随机性,并帮助您存储和注释…

北京WordPress建站公司

北京wordpress建站&#xff0c;就找北京wordpress建站公司 http://wordpress.zhanyes.com/beijing

深入解析大数据体系中的ETL工作原理及常见组件

** 引言 关联阅读博客文章&#xff1a;探讨在大数据体系中API的通信机制与工作原理 关联阅读博客文章&#xff1a;深入理解HDFS工作原理&#xff1a;大数据存储和容错性机制解析 ** 在当今数字化时代&#xff0c;大数据处理已经成为了企业成功的重要组成部分。而在大数据处…

C#学习笔记 面试提要

冒泡 for (int m 0; m < arr.Length; m) { for (int n 0; n < arr.Length - 1 - m; n) { if (arr[n] > arr[n1]) { int temp arr[n]; arr[n] arr[n 1]; arr[n1] temp; } } } 选择 for (int m 0; m < arr.Length; m) { int index 0; for (int n 1; n < …