【学生管理系统】用户登录三种验证方式—图片验证、短信验证、邮件验证

news2024/11/28 4:43:35

目录

一、页面需求展示

二、验证方式—按钮组件

三、手机短信验证

四、邮件验证

五、图片验证邮件验证

💟 创作不易,不妨点赞💚评论❤️收藏💙一下


一、页面需求展示


二、验证方式—按钮组件

 2.1前端

<el-form-item label="验证方式">
        <el-button type="primary" icon="el-icon-phone" circle @click.prevent="verModeFn(1)"></el-button>
        <el-button type="success" icon="el-icon-message" circle @click.prevent="verModeFn(2)"></el-button>
        <el-button type="warning" icon="el-icon-camera" circle @click.prevent="verModeFn(3)"></el-button>
</el-form-item>
<el-form-item v-if="verMode == 1" label="手机号" prop="telephone">
</el-form-item>
<el-form-item v-if="verMode == 1" label="短信验证">
</el-form-item>
<el-form-item v-if="verMode == 2" label="邮箱" prop="email">
</el-form-item>
<el-form-item v-if="verMode == 2" label="邮件验证">
</el-form-item>
<el-form-item v-if="verMode == 3" label="图片验证">
</el-form-item>
<script>

export default {
  data() {
    return {
      verMode : '3' ,  //验证方式 
    }
  },
  methods:{
    //验证方式点击方法
    verModeFn(vo){
      this.verMode = vo
    },
  
}
</script>

三、手机短信验证

3.1 前端

<el-form-item v-if="verMode == 1" label="手机号" prop="telephone">
        <el-row>
          <el-col :span="13">
              <el-input v-model="user.telephone"></el-input>
          </el-col>
          <el-col :span="11">
              <el-button type="success" style="margin-left: 5px;padding: 10px 6px" 
              @click.prevent="sendSmsCodeFn"
              :disabled="btnDisabled"
              >短信发送{{seconds}}秒</el-button>
          </el-col>
        </el-row>  
      </el-form-item>
      <el-form-item v-if="verMode == 1" label="短信验证">
        <el-row>
          <el-col :span="13">
              <el-input v-model="user.codeSms"></el-input>
          </el-col>
          <el-col :spam="11">
              <span style="color:red">{{errorMsg.message}}</span>
          </el-col>
        </el-row>
</el-form-item>
<script>

export default {
  data() {
    return {
      user:{
        userName:'',
        password:'',
        telephone:'',    //手机号
      },
      errorMsg: {},
      verMode : '3' ,  //验证方式
      btnDisabled : false ,  //倒计时控制变量,可用不可用
      seconds: 10 ,    //默认倒计时秒数
      timer : null   ,  //接收定时器,清除定时器
  },
  methods:{
    //验证方式点击方法
    verModeFn(vo){
      this.verMode = vo
    },
    //发送短信验证--
    async sendSmsCodeFn(){
      let {data:baseResult} = await this.$axios.post(`/user-service/sms/code`,this.user);
      this.errorMsg = baseResult ;
        //按钮不可用
        this.btnDisabled = true ;
        //倒计时
        this.timer = setInterval(() => {
          if(this.seconds <= 1){
            //结束,重置秒数
            this.seconds = 10 ;
            this.btnDisabled = false ;
            //停止定时器
            clearInterval(this.timer);
          }else{
            this.seconds-- ;
          }
        }, 1000);
    },
  
}
</script>

3.2后端

 生成短信验证码,保存在redis中

@RestController
@RequestMapping("/sms")
public class SmsController {
    @Resource
    private StringRedisTemplate stringRedisTemplate ;

    @PostMapping("/code")
    public BaseResult sendSms(@RequestBody TbUser user){
        //获取当前毫秒值
        long start = System.currentTimeMillis();
        try {
            //发送短信
            //1.生成验证码,随机4位数
            String code = RandomStringUtils.randomNumeric(4);
            System.out.println("短信验证码:" + code);
            //存放在redis中
            stringRedisTemplate.opsForValue().set("smsPhone"+user.getTelephone(),code,1, TimeUnit.HOURS);
            //发送短信
            SendSmsResponse smsResponse = SmsUtil.sendSms(user.getTelephone(), user.getUserName(), code, "", "");
            if ("OK".equalsIgnoreCase(smsResponse.getCode())){
                return BaseResult.ok("短信发送成功,请查收!");
            }else {
                return BaseResult.error(smsResponse.getMessage());
            }
        } catch (ClientException e) {
            //获取结束时间毫秒值
            long end = System.currentTimeMillis();
            System.out.println(end -start);
            return BaseResult.error("短信发送失败!");
        }
    }

}

点击登录进行短信验证码判断是否正确

@RestController
@RequestMapping("/user")
public class UserController {
    @Resource
    private UserService userService ;

    @Resource
    private JwtProperties jwtProperties ;

    @Resource
    private StringRedisTemplate stringRedisTemplate ;


    @PostMapping("/login")
    public BaseResult login(@RequestBody TbUser user) throws Exception {
        //手机短信验证
        if (user.getCodeSms() != null) {
            //获取短信验证码
            String sms = "smsPhone" + user.getTelephone() ;
            String keySms = stringRedisTemplate.opsForValue().get(sms);
            stringRedisTemplate.delete(keySms);
            if (keySms == null ){
                return BaseResult.error("短信验证码无效!");
            }
            if (!keySms.equalsIgnoreCase(user.getCodeSms())){
                return BaseResult.error("短信验证码错误!");
            }
        }

        //登录对用户名和密码进行判断
        //调用userService接口中的方法login进行实现类编写,判断用户名和密码是否正确
        TbUser findUser = userService.login(user);
        if (findUser != null){
            //设置token
            String token = JwtUtils.generateToken(findUser, jwtProperties.getExpire(), jwtProperties.getPrivateKey());
            return BaseResult.ok("登录成功,欢迎"+findUser.getUserName(),findUser).append("token",token);
        }else {
            return BaseResult.error("用户名或密码不正确!");
        }
    }
}

四、邮件验证

4.1 前端

<el-form-item v-if="verMode == 2" label="邮箱" prop="email">
        <el-row>
          <el-col :span="13">
             <el-input v-model="user.email"></el-input>
          </el-col>
          <el-col :span="11">
              <el-button type="success" style="margin-left: 5px;padding: 10px 6px"
               @click.prevent="emailCodeFn"
               :disabled="btnDisabled"
               >邮件发送{{seconds}}秒</el-button>
          </el-col>
        </el-row>  
      </el-form-item>
      <el-form-item v-if="verMode == 2" label="邮件验证">
        <el-row>
          <el-col :span="13">
              <el-input v-model="user.emailCode"></el-input>
          </el-col>
          <el-col :spam="11">
              <span style="color:red">{{errorMsg.message}}</span>
          </el-col>
        </el-row>
</el-form-item>
<script>

export default {
  data() {
    return {
      user:{
        userName:'',
        password:'',
        email : ''      
      },
      errorMsg: {},
      verMode : '3' ,  //验证方式
      btnDisabled : false ,  //倒计时控制变量,可用不可用
      seconds: 10 ,    //默认倒计时秒数
      timer : null   ,  //接收定时器,清除定时器
  },
  methods:{
    //验证方式点击方法
    verModeFn(vo){
      this.verMode = vo
    },
    //发送邮箱验证
    async emailCodeFn(){
      let {data:baseResult} = await this.$axios.post(`/user-service/email/send`,this.user);
      this.errorMsg = baseResult ;
      if(baseResult.code == 20000){
          this.btnDisabled = true ;
          this.timer = setInterval(() => {
            if(this.seconds <= 1){
              this.seconds = 10 ;
              this.btnDisabled = false ;
              clearInterval(this.timer);
          }else {
            this.seconds-- ;
          }
        }, 1000);
      }
    }
  
}
</script>

4.2后端

  生成短信验证码,保存在redis中

@RestController
@RequestMapping("/email")
public class EmailController {
    @Resource
    private StringRedisTemplate stringRedisTemplate ;
    @Resource
    private JavaMailSender javaMailSender ;

    @PostMapping("/send")
    public BaseResult send(@RequestBody TbUser tbUser){
        try {
            //随机生成验证码
            String code = RandomStringUtils.randomNumeric(4);
            System.out.println("邮件验证码:"+code);
            //保存到redis
            String key = "email"+tbUser.getUserName();
            stringRedisTemplate.opsForValue().set(key,code,1, TimeUnit.HOURS);
            //发送
            EmailUtils.sendEmail(javaMailSender,tbUser.getEmail(),"邮件验证码为:"+code);
            //返回
            return BaseResult.ok("邮件发送成功!");
        } catch (Exception e) {
            e.getMessage();
            return BaseResult.error("发送邮件失败!");
        }
    }
}

点击登录进行邮件验证码判断是否正确

@RestController
@RequestMapping("/user")
public class UserController {
    @Resource
    private UserService userService ;

    @Resource
    private JwtProperties jwtProperties ;

    @Resource
    private StringRedisTemplate stringRedisTemplate ;


    @PostMapping("/login")
    public BaseResult login(@RequestBody TbUser user) throws Exception {
       //邮箱验证
        if (user.getEmailCode() != null){
            //获取邮箱验证码
            String keyEmail = "email"+user.getUserName();
            String redisEmail = stringRedisTemplate.opsForValue().get(keyEmail);
            stringRedisTemplate.delete(keyEmail);
            if (redisEmail == null){
                return BaseResult.error("email验证码无效!");
            }
            if (!redisEmail.equalsIgnoreCase(user.getEmailCode())){
                return BaseResult.error("email验证码错误!");
            }
        }

        //登录对用户名和密码进行判断
        //调用userService接口中的方法login进行实现类编写,判断用户名和密码是否正确
        TbUser findUser = userService.login(user);
        if (findUser != null){
            //设置token
            String token = JwtUtils.generateToken(findUser, jwtProperties.getExpire(), jwtProperties.getPrivateKey());
            return BaseResult.ok("登录成功,欢迎"+findUser.getUserName(),findUser).append("token",token);
        }else {
            return BaseResult.error("用户名或密码不正确!");
        }
    }
}

五、图片验证邮件验证

5.1 前端

<el-form-item v-if="verMode == 3" label="图片验证">
        <el-row>
          <el-col :span="11">
            <el-input v-model="user.verifyCode"></el-input>
          </el-col>
          <el-col :span="13" >
            <img :src="imgSrc"  v-if="user.userName != ''"
            style="width: 90px;height: 39px;padding-left: 4px"
            @click.prevent="changeVerifyCode"
            />
            <span>看不清?<a href="" @click.prevent="changeVerifyCode">换一张</a></span>
          </el-col>
        </el-row>
        <span style="color:red">{{errorMsg.message}}</span>
      </el-form-item>
<el-form-item>
<script>

export default {
  data() {
    return {
      user:{
        userName:'',
        password:'',
        verifyCode:'', //图片验证码
      },
      imgSrc: '',    //绑定图片
      errorMsg: {},
      verMode : '3' ,  //验证方式
  },
  methods:{
    //验证方式点击方法
    verModeFn(vo){
      this.verMode = vo
    },
    //图片验证码
    changeVerifyCode(){
      if(this.user.userName){
        //使用时间对验证码进行标识
        //与用户名进行绑定,只要用户名失去焦点就对图片验证码进行一个更新
        this.imgSrc = `http://localhost:10010/user-service/verifycode?userName=${this.user.userName}&t=${new Date().getTime()}` 
      }else{
        this.errorMsg.message = '用户不能为空';
      }     
    },
  
}
</script>

5.2后端

 生成图片验证码,保存在redis中

@Controller
@RequestMapping("/verifycode")
public class VerifyCodeController {
    @Resource
    private StringRedisTemplate stringRedisTemplate ;

    @GetMapping
    public void verifyCodeFn(String userName,HttpServletResponse response) throws Exception {
        //准备数据
        //字体只显示大写,去掉了1,0,i,o几个容易混淆的字符
        String VERIFY_CODES = "23456789ABCDEFGHJKLMNPQRSTUVWXYZ";

        int IMG_WIDTH = 72;
        int IMG_HEIGTH = 27;
        Random random = new Random();
        //创建图片
        BufferedImage image = new BufferedImage(IMG_WIDTH, IMG_HEIGTH, BufferedImage.TYPE_INT_RGB);
        //画板
        Graphics g = image.getGraphics();
        //填充背景
        g.setColor(Color.WHITE);
        g.fillRect(1,1,IMG_WIDTH-2,IMG_HEIGTH-2);

        g.setFont(new Font("楷体", Font.BOLD,25));

        StringBuilder sb = new StringBuilder();
        //写字
        for(int i = 1 ; i <= 4 ; i ++){
            //随机颜色
            g.setColor(new Color(random.nextInt(255),random.nextInt(255),random.nextInt(255)));
            int len = random.nextInt(VERIFY_CODES.length());
            String str = VERIFY_CODES.substring(len,len+1);
            sb.append(str);
            g.drawString(str, IMG_WIDTH / 6 * i , 22 );
        }

        //将验证码存放到redis
        //设置名称login+username ,过期时间1小时
        stringRedisTemplate.opsForValue().set( "login" + userName , sb.toString() , 1 , TimeUnit.HOURS);

        // 生成随机干扰线
        for (int i = 0; i < 30; i++) {
            //随机颜色
            g.setColor(new Color(random.nextInt(255),random.nextInt(255),random.nextInt(255)));
            int x = random.nextInt(IMG_WIDTH - 1);
            int y = random.nextInt(IMG_HEIGTH - 1);
            int x1 = random.nextInt(12) + 1;
            int y1 = random.nextInt(6) + 1;
            g.drawLine(x, y, x - x1, y - y1);
        }
        //响应到浏览器
        ImageIO.write(image,"jpeg", response.getOutputStream());
    }
}

点击登录进行图片验证码判断是否正确

@RestController
@RequestMapping("/user")
public class UserController {
    @Resource
    private UserService userService ;

    @Resource
    private JwtProperties jwtProperties ;

    @Resource
    private StringRedisTemplate stringRedisTemplate ;


    @PostMapping("/login")
    public BaseResult login(@RequestBody TbUser user) throws Exception {
         //校验图片验证码
        if (!user.getVerifyCode().equals("")) {
            //获取验证码
            String key = "login" + user.getUserName() ;
            String verify = stringRedisTemplate.opsForValue().get(key);
            //删除验证码
            stringRedisTemplate.delete(key);
            if (verify == null) {
                return BaseResult.error("图片验证码无效!");
            }
            if (!verify.equalsIgnoreCase(user.getVerifyCode())) {
                return BaseResult.error("图片验证码错误!");
            }
        }

        //登录对用户名和密码进行判断
        //调用userService接口中的方法login进行实现类编写,判断用户名和密码是否正确
        TbUser findUser = userService.login(user);
        if (findUser != null){
            //设置token
            String token = JwtUtils.generateToken(findUser, jwtProperties.getExpire(), jwtProperties.getPrivateKey());
            return BaseResult.ok("登录成功,欢迎"+findUser.getUserName(),findUser).append("token",token);
        }else {
            return BaseResult.error("用户名或密码不正确!");
        }
    }
}

写到最后

四季轮换,已经数不清凋零了多少, 愿我们往后能向心而行,一路招摇胜!

🐋 你的支持认可是我创作的动力

💟 创作不易,不妨点赞💚评论❤️收藏💙一下

😘 感谢大佬们的支持,欢迎各位前来不吝赐教

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

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

相关文章

【Linux】第十章 进程间通信(管道+system V共享内存)

&#x1f3c6;个人主页&#xff1a;企鹅不叫的博客 ​ &#x1f308;专栏 C语言初阶和进阶C项目Leetcode刷题初阶数据结构与算法C初阶和进阶《深入理解计算机操作系统》《高质量C/C编程》Linux ⭐️ 博主码云gitee链接&#xff1a;代码仓库地址 ⚡若有帮助可以【关注点赞收藏】…

工作流的例子

工作流的例子目录概述需求&#xff1a;设计思路实现思路分析1.配置bean2.examples3.no bean4.activiti-api-basic-process-example5.taskspringweb参考资料和推荐阅读Survive by day and develop by night. talk for import biz , show your perfect code,full busy&#xff0c…

C++ 多态类型

多态 C在面向对象中&#xff0c;多态就是不同对象收到相同消息&#xff0c;执行不同的操作。在程序设计中&#xff0c;多态性是名字相同的函数&#xff0c;这些函数执行不同或相似的操作&#xff0c;这样就可以用同一个函数名调用不同内容的函数。简而言之“一个接口&#xff…

2022 国赛postgresql

安装postgresql配置postgresql [root@linux3 ~]# postgresql-setup --initdb //初始化数据库Initializing database in ‘/var/lib/pgsql/data’Initialized, logs are in /var/lib/pgsql/initdb_postgresql.log[root@linux3 ~]# systemctl enable postgresql.service Created …

澳洲最热门职业,护士排第一,医生竟然不如程序员?

2022澳洲最新的职业紧缺名单出炉了&#xff0c;令人惊讶的是护士竟然排行第一名&#xff0c;可见澳洲的医疗人力资源紧缺的问题。 既然人力资源紧缺&#xff0c;那么首当其冲的医生作为高学历且同属医疗行业的代表理应收到重视&#xff0c;然而令人意外的是&#xff0c;通过榜单…

Linux一篇入门(以Ubuntu为例)

一、Linux与Windows区别 Linux&#xff1a;无盘符&#xff0c;只有一个根目录&#xff08;/&#xff09; Windows&#xff1a;有盘符 二、目录相关常见命令 Linux命令格式&#xff1a; cmd -option parameter cdm命令&#xff0c;就是一个操作 parameter一般是要做的对象…

韩国程序员面试考什么?

大家好&#xff0c;我是老三&#xff0c;在G站闲逛的时候&#xff0c;从每日热门上&#xff0c;看到一个韩国的技术面试项目&#xff0c;感觉有点好奇&#xff0c;忍不住点进去看看。 韩国的面试都考什么&#xff1f;有没有国内的卷呢&#xff1f; 可以看到&#xff0c;有8.…

抽象类和接口

文章目录 前言 一、今日回顾 1.《高等数学》 2.阅读&#xff1a; 3.英语&#xff1a; 二、编程的那些事 1.引入库 2.读入数据 总结 前言 一、今日回顾 1.《高等数学》 2.阅读&#xff1a; 3.英语&#xff1a; 二、编程的那些事 1.抽象类的描述 在java中&#xff0…

一次函数与二次函数的联系

首先&#xff0c;无论是一次函数还是二次函数&#xff0c;都是函数&#xff0c;所以便可以从表达式&#xff0c;图像&#xff0c;函数的四个性质&#xff08;即有界性&#xff0c;单调性&#xff0c;奇偶性&#xff0c;周期性&#xff09;去看他们之间的联系 一次函数与二次函…

2022第8届中国大学生程序设计竞赛CCPC桂林站, 签到题4题

文章目录A. LilyM.Youth FinaleC.Array ConcatenationE.Draw a triangleA. Lily A. Lily time limit per test1 second memory limit per test512 megabytes inputstandard input outputstandard output They serve the purpose of changing hydrogen into breathable oxygen,…

MySQL数据库 -- 库和表的操作

关于数据库方面&#xff0c;还是需要多多练习的&#xff0c;否则很多指令不容易记住&#xff0c;所以大家也要在自己的电脑上多写写&#xff0c;熟悉熟悉~ 目录 库的操作 创建数据库 操纵数据库 查看数据库 显示创建语句 修改数据库 数据库的删除 数据库备份和恢复 …

重学数据库基础

幸福找到我&#xff0c;幸福说&#xff1a;“瞧这个诗人&#xff0c;他比我本人还要幸福” 一、数据库相关概念 数据库 存储数据的仓库&#xff0c;数据是有组织的进行存储英文&#xff1a;DataBase&#xff0c;简称 DB 数据库管理系统 管理数据库的大型软件英文&#xff1a;Da…

CSI室内指纹定位——相关通信名词解释

目录 1、无线信道 2、时域与频域 3、信道频率响应&#xff08;Channel Frequency Response,CFR&#xff09; 4、信道冲激响应&#xff08;Channel Impulse Response, CIR&#xff09; 5、信道带宽 6、带宽 7、子载波 9、波长 10、频率 11、振幅 12、相位 13、相位差…

高数值孔径(NA)物镜的聚焦分析

1. 摘要 高NA物镜广泛用于光刻&#xff0c;显微等技术。因此&#xff0c;聚焦仿真中考虑光的矢量性质至关重要。VirtualLab可以非常便捷地对此类镜头进行光线追迹和场追迹分析。通过场追迹&#xff0c;可以清楚地观察由于矢量效应引起的聚焦光斑失对称现象。利用相机探测器和电…

第十四届蓝桥杯(Web应用开发)模拟赛1期-大学组

数据类型检测 请看这篇数据类型检测 渐变色背景生成器 html <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta http-equiv"X-UA-Compatible" content"IEedge" /><meta name&…

java面试官:程序员,请你告诉我是谁把公司面试题泄露给你的?

前情提要&#xff1a; 面试官&#xff1a;你好&#xff01;请先做一下自我介绍&#xff01; 程序员&#xff1a;balabalabala... 前戏先过了.... 面试官&#xff1a;先介绍SpringCloud核心组件及其作用 程序员&#xff1a;SpringCloud由以下5个核心组件构成...另外&#x…

MySQL事务基本操作(方式1)

在观看本文前 你需要了解什么事事务 如果不太了解 可以先查看我的文章 MySQL事务基本概念 首先 我们这里有一张 staff 用户表 然后来一波 减岁交易大法 赵敏买个了 黄飞鸿十年时光 那么就是 先查询确认赵敏加上十岁不会过百 将赵敏年龄加十岁 确认黄飞鸿减去十岁不会小于零 然…

Java项目(三)-- SSM开发社交网站(9)--后台图书管理功能

后台图书管理功能 富文本编辑器wangEditor 基于javascript与css开发是Web富文本编辑器&#xff0c;轻量、简洁、易用、开源免费。 代码演示 我们在test.ftl中添加富文本编辑器演示下 <!DOCTYPE html> <html lang"en"> <head><meta charset&…

CMake中string的使用

CMake中的string命令用于字符串操作,其格式如下&#xff1a; Search and Replacestring(FIND <string> <substring> <out-var> [...])string(REPLACE <match-string> <replace-string> <out-var> <input>...)string(REGEX MATCH &l…

【数据库Redis】Redis五种基本数据结构以及三种配置方式——默认配置、运行配置、配置文件启动

文章目录一、初识Redis1.1 了解Redis1.2 Redis特性1.3 Redis使用场景Redis不适合场景1.4 用好Redis的建议1.5 正确安装并启动Redis在Linux上安装Redis在Windows上安装Redis配置、启动、操作、关闭Redis1)、启动Redis2)、Redis命令行客户端3)、停止Redis服务1.6 Redis重大版本一…