当前位置: 首页 > news >正文

手机号发验证码实现用户注册登录

一.技术及思路

 二.案例编写

  • 配置环境:使用docker新建redis,mysql,rabbitmq的容器

  • MySQL:
  • 启动docker服务
  • systemctl start docker
  • 查看docker服务状态
  • systemctl status docker
  • 查看目录
  • 进入mysql目录下,然后新创建一个容器,熟悉一下docker部署MySQL
  • cd root/mysql/
  • 方式1
  • docker run -id -p 3306:3306 \
    --name=c_mysql2 \
    -v $PWD/conf:/etc/mysql/conf.d \
    -v $PWD/logs:/logs \
    -v $PWD/data:/var/lib/mysql \
    -e MYSQL_ROOT_PASSWORD=root \
    mysql:5.7
    

  • 方式2
  •  docker run --name=c_mysql -d -p 3306:3306 -e MYSQL_ROOT_PASSWORD=root mysql:5.7
  • 查看容器运行状态
  • docker ps -a
  • 启动c_mysql容器
  • docker start c_mysql
  • 到这一步的时候,出错了,新的MySQL容器和旧的MySQL容器都启动不了了,而且后来将新的容器删除之后,旧的容器依旧启动不了,也不知道啥情况(前面是用第一种方式创建,不行就请教了老师,改成了第二种方式)
  • 然后到用Navicat连接诶数据库
  • 然后现在开始创建项目,配置环境

  • 自动创建springboot项目,导入依赖
  •   <!--整合mybatis-plus-->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>5.1.49</version>
            </dependency>
     
            <dependency>
                <groupId>com.baomidou</groupId>
                <artifactId>mybatis-plus-boot-starter</artifactId>
                <version>3.0.5</version>
            </dependency>
     
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.12</version>
            </dependency>
     
             <!--加密组件,apache-->
            <dependency>
                <groupId>commons-codec</groupId>
                <artifactId>commons-codec</artifactId>
                <version>1.3</version>
            </dependency>
     
            <!--redis依赖-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-redis</artifactId>
            </dependency>
     
            <!--jwt-->
            <dependency>
                <groupId>io.jsonwebtoken</groupId>
                <artifactId>jjwt</artifactId>
                <version>0.9.1</version>
            </dependency>
    
             <!--AMQP依赖-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-amqp</artifactId>
            </dependency>
  • 然后,根据我们的需要,我们现在需要在这个父项目当中,创建两个子模块(注意要创建maven项目,因为springboot项目本身就已经继承了一个父类,那么就会导致我们无法再继承刚刚我们创建的父项目)
  • 在这两个模块当中,一个用来实现发送短消息,登录注册这三个功能,另一个用来实现收验证码的功能
  • 新建模块1:Pubreg,手写启动类,加入核心配置文件,里面增加mq的配置
  • package com.pro;
    
    import org.mybatis.spring.annotation.MapperScan;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    
    @SpringBootApplication
    @MapperScan(value = "com.pro.mapper")
    public class PubRegApp {
        public static void main(String[] args) {
            SpringApplication.run(PubRegApp.class,args);
        }
    }
    
  • #mq
    spring.rabbitmq.host=192.168.8.171
    #通信端口
    spring.rabbitmq.port=5672
    spring.rabbitmq.username=rabbit
    spring.rabbitmq.password=rabbit
    spring.rabbitmq.virtual-host=/
    
  • package com.pro.config;
    
    import org.springframework.amqp.core.Queue;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    
    //标识了下面这个注解,就代表是配置类:相当于以前的applicationContext.xml文件
    @Configuration
    public class PubConfig {
        @Bean
        public Queue queue(){
            return new Queue("yzmQueue");
        }
    }
    

  • 然后在这个模块里面开始写我们的发送验证码和登录业务
    • 思路:业务层,我们需要根据前端传过来的用户名随机生成验证码,将用户名和密码存进reids,并且发送到yzmQueue队列中
    • package com.pro.service;
      
      import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
      import com.baomidou.mybatisplus.extension.api.R;
      import com.pro.domain.User;
      import com.pro.mapper.UserMapper;
      import org.springframework.amqp.rabbit.core.RabbitTemplate;
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.data.redis.core.RedisTemplate;
      import org.springframework.stereotype.Service;
      
      import java.time.Duration;
      import java.util.HashMap;
      import java.util.Map;
      import java.util.Random;
      
      @Service
      public class UserServiceImpl implements UserService {
      
          @Autowired
          private UserMapper userMapper;
      
          @Autowired
          private RedisTemplate redisTemplate;
      
          @Autowired
          private RabbitTemplate rabbitTemplate;
      
      
          /**
           * 发送验证码
           * @param username
           */
          @Override
          public void proYzm(String username) {
              Random random = new Random();
              int yzm = random.nextInt(9000)+1000;//生成一个1000到10000之间的四位数验证码
              //用用户名做键,验证码做值,存进Redis,并设置一分钟的存活时间
              String YZM = String.valueOf(yzm);
              redisTemplate.opsForValue().set(username,YZM, Duration.ofSeconds(120));
              //将yzmQueue作为队列名,验证码和手机号的作为消息发送到消息队列当中,前提是我们已经写了配置类,创建了这个队列
              Map<Object,Object> map = new HashMap();
              map.put("username",username);
              map.put("yzm",yzm);
              rabbitTemplate.convertAndSend("yzmQueue",map);
          }
      
          /**
           * 验证是否已经发送过验证码
           * @param username
           * @return
           */
          public String checkYzm(String username){
              String redisData = (String) redisTemplate.opsForValue().get(username);
              return redisData;
          }
      
          @Override
          public String checkLogin(String username,String yzm) {
              String redisYzm = (String) redisTemplate.opsForValue().get(username);
              QueryWrapper queryWrapper = new QueryWrapper();
              queryWrapper.eq("username",username);
              User user = userMapper.selectOne(queryWrapper);
              //如果用户不存在,注册并判断是否登录成功
              if(user == null){
                  if(yzm.equals(redisYzm)){
                      User user1 = new User();
                      user1.setUsername(username);
                      userMapper.insert(user1);
                      return "尊贵的"+username+"用户,您已注册并登录成功!";
                  }else {
                      return "验证码错误或已过期!";
                  }
              }else {//用户存在,直接判断是否可以登录
                  if(redisYzm.equals(yzm)){
                      return "尊贵的"+username+"用户,欢迎回来!";
                  }else {
                      return "验证码错误或已过期!";
                  }
              }
          }
      }
      
      package com.pro.controller;
      
      import com.pro.service.UserService;
      import com.pro.util.R;
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.web.bind.annotation.GetMapping;
      import org.springframework.web.bind.annotation.PostMapping;
      import org.springframework.web.bind.annotation.RestController;
      
      @RestController
      public class UserController {
          @Autowired
          private UserService userService;
      
      
          /**
           * 发验证码
           * @param username
           * @return
           */
          @PostMapping("/proYzm")
          public R proYzm (String username){
              String checkYzm = userService.checkYzm(username);
              if(checkYzm == null){
                  userService.proYzm(username);
                  return new R(200,"验证码发送成功!");
              }
              return new R(300,"请两分钟之后再发验证码!");
          }
      
          /**
           * 登录判断
           * @param username
           * @param yzm
           * @return
           */
          @PostMapping("/checkLogin")
          public String checkLogin(String username,String yzm){
              String s = userService.checkLogin(username, yzm);
              return s;
          }
      }
      
    • 效果:
    • Redis里面可以看到信息只能存活我们设置的60秒
  • 测试好发送验证码,我们现在来写接收验证码

  • 首先建一个模块conReg,手写启动类,加入核心配置文件,里面增加mq的配置
  • 写一个监听类来监听队列当中的验证码消息,模拟接收验证码
  • package com.pro.listener;
    
    import org.springframework.amqp.rabbit.annotation.RabbitListener;
    import org.springframework.stereotype.Component;
    
    import java.util.Map;
    
    @Component
    public class SpringRabbitListener {
        /*  @RabbitListener(queues = "java")
          public void listenerQueue(String msg){
              System.out.println("消费者接受到了消息:"+msg);
          }
      */
        @RabbitListener(queues = "yzmQueue")
        public void listenerWorkQueue1(Map map)throws Exception{
            System.out.println("【验证密码】您的验证码为:"+map.get("yzm")+"。尊敬的"+map.get("username")+"客户,以上验证密码2分钟内有效,请勿泄露或转发他人。【湖北移动 移动认证】");
        }
    
    }
    
  • 然后如果是已注册用户,登录会显示欢迎回来

  • 验证码错误或者过期,就会提示验证码过期或错误,这里我没有设置具体是用户名错误还是验证码错误了。

  •  

  • 遇到的问题
    • 数据库ID没有设自动递增,插入user的时候,用null去调用get方法
  • 后续需要改进:加入token,未登录不能操作,前端页面实现。

相关文章:

  • 程序员缺乏经验的 7 种表现,你中了几个?
  • Spring框架中的核心技术之AOP
  • 用户体验与响应式字体二三事|rem单位与flexible.js、rpx单位与css媒体查询
  • 408 | 【2009年】计算机统考真题 自用回顾知识点整理
  • MyMusic 重点实现
  • 云计算敏捷团队的 10 个最佳实践工具
  • 阿里面试官终于把多年总结的Java八股文PDF版分享出来了,帮我金九银十拿下4个offer
  • java毕业设计超市管理系统Mybatis+系统+数据库+调试部署
  • 计算机网络 第 1 章 计算机网络概述
  • 如何转换图片格式?教你三招一键轻松转换图片格式
  • 【从小白到大白04】Linux基本权限
  • Unity_飞机大战_防止单例随场景销毁和跨场景两个物体脚本问题_自动加载物体挂载脚本的两种方式
  • taro 兼容支付宝小程序和微信小程序<七>-- 上传图片及图片转base64
  • 【附源码】计算机毕业设计SSM汽车交易平台
  • 购买域名-腾讯云
  • 【跃迁之路】【463天】刻意练习系列222(2018.05.14)
  • flask接收请求并推入栈
  • JavaScript/HTML5图表开发工具JavaScript Charts v3.19.6发布【附下载】
  • k个最大的数及变种小结
  • Python socket服务器端、客户端传送信息
  • Vue官网教程学习过程中值得记录的一些事情
  • 警报:线上事故之CountDownLatch的威力
  • 看域名解析域名安全对SEO的影响
  • 使用API自动生成工具优化前端工作流
  • 与 ConTeXt MkIV 官方文档的接驳
  • MiKTeX could not find the script engine ‘perl.exe‘ which is required to execute ‘latexmk‘.
  • 白色的风信子
  • 大数据全解:定义、价值及挑战
  • 完善智慧办公建设,小熊U租获京东数千万元A+轮融资 ...
  • ​MySQL主从复制一致性检测
  • ​一帧图像的Android之旅 :应用的首个绘制请求
  • ​总结MySQL 的一些知识点:MySQL 选择数据库​
  • #define,static,const,三种常量的区别
  • #我与Java虚拟机的故事#连载03:面试过的百度,滴滴,快手都问了这些问题
  • (zt)最盛行的警世狂言(爆笑)
  • (二)七种元启发算法(DBO、LO、SWO、COA、LSO、KOA、GRO)求解无人机路径规划MATLAB
  • (力扣记录)1448. 统计二叉树中好节点的数目
  • (轉貼) 寄發紅帖基本原則(教育部禮儀司頒布) (雜項)
  • .bat批处理(三):变量声明、设置、拼接、截取
  • .net framwork4.6操作MySQL报错Character set ‘utf8mb3‘ is not supported 解决方法
  • .NET WebClient 类下载部分文件会错误?可能是解压缩的锅
  • .net 发送邮件
  • .NET 回调、接口回调、 委托
  • .net企业级架构实战之7——Spring.net整合Asp.net mvc
  • /proc/interrupts 和 /proc/stat 查看中断的情况
  • [ 代码审计篇 ] 代码审计案例详解(一) SQL注入代码审计案例
  • [20170713] 无法访问SQL Server
  • [AIGC] Java 和 Kotlin 的区别
  • [AIGC] 开源流程引擎哪个好,如何选型?
  • [BZOJ 4034][HAOI2015]T2 [树链剖分]
  • [C/C++]数据结构 栈和队列()
  • [C++] cout、wcout无法正常输出中文字符问题的深入调查(1):各种编译器测试
  • [CSS]CSS 的背景
  • [Docker]十一.Docker Swarm集群raft算法,Docker Swarm Web管理工具
  • [hdu 3746] Cyclic Nacklace [kmp]