前后端分离实现验证码

实现流程

1、前端登录页面加载时发送请求来请求验证码接口

2、服务器端接收到用户验证码的请求之后,使用工具类来生成验证码(base64)

3、将获取到的 验证码 对应的code 保存到 redis 中并设置该码的有效时间,一般建议使用 UUID 作为key,code 做value 来进行保存。直接将 验证码对应的 base64码 和 对应的UUID 响应给前端

4、前端输入完毕之后,发送登录请求时,将接收到的 UUID 作为参数一起携带到服务器端。

5、服务器端接收端到用户请求之后,根据携带来的UUID 从redis中取出对应的数据,再根据用户输入的code来进行判断是否相对即可

实现步骤:redis这里就不做说明了,直接使用springboot的 jedis 即可

1、引入hutool的验证码依赖

<!-- hutool --><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.5.7</version></dependency>

2、自定义一个用来保存 验证码 信息的 实体类

package com.sany.crane.oa.core.entity;import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;@Data
@NoArgsConstructor
@AllArgsConstructor
public class ImgResult {@ApiModelProperty("该验证码对应的UUID")private String imgUUID;@ApiModelProperty("该验证码对应的base64加密格式")private String img;@ApiModelProperty("该验证码对应的具体码")private String code;
}

3、对应的 验证码 生成工具类

package com.sany.crane.oa.common.util;import cn.hutool.core.codec.Base64;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Random;@Slf4j
@Data
public class CaptchaUtil {//验证码个数private int count = 4;//验证码宽度,且设置每个字的宽度private int width = count * 50;//验证码高度private int height = 50;//图片验证码keyprivate String code = "";//bufferedImageprivate BufferedImage bufferedImage;//测试写入public static void main(String[] args) {long startend = System.currentTimeMillis();CaptchaUtil captchaUtil = new CaptchaUtil();//默认验证码位数为4,我这里设为5captchaUtil.setCount(5);//得到缓冲区BufferedImage image = captchaUtil.getImage();//得到真实验证码String code = captchaUtil.getCode();long endTime = System.currentTimeMillis();System.out.println("验证码为:" + code + "\n花费时间为:" + (endTime - startend) + "\n到E盘根目录下看,文件名为11.jpg");}public BufferedImage getImage() {//图片缓冲区BufferedImage image = new BufferedImage(width, height, 1);//获得笔Graphics graphics = image.getGraphics();//设置初始画笔为白色graphics.setColor(new Color(255, 255, 254));//画满整个图,也就是把图片先变为白色graphics.fillRect(0, 0, width, height);Random rd = new Random();//设置字体Font font = new Font("宋体", Font.PLAIN, 35 + rd.nextInt(10));graphics.setFont(font);char[] chars = "qweCRYHrtasdfBxy678934VTGopNUFKuighjklzSXEDLOP12cvbnmQAZWJMI50".toCharArray();//画验证码for (int i = 0; i < count; i++) {String string = "";string += chars[rd.nextInt(chars.length)] + "";graphics.setColor(new Color(rd.nextInt(254), rd.nextInt(254), rd.nextInt(254)));graphics.drawString(string, 55 * i + rd.nextInt(10), 27 + rd.nextInt(15));code += string;}//干扰点for (int i = 0; i < 25 * count; i++) {graphics.setFont(new Font("宋体", Font.PLAIN, 15));String string = ".";graphics.setColor(new Color(rd.nextInt(255), rd.nextInt(255), rd.nextInt(255)));graphics.drawString(string, rd.nextInt(width), rd.nextInt(height));}//干扰线for (int i = 0; i < count + count / 2; i++) {graphics.setFont(new Font("宋体", Font.PLAIN, 10));graphics.setColor(new Color(rd.nextInt(255), rd.nextInt(255), rd.nextInt(255)));graphics.drawLine(rd.nextInt(width), rd.nextInt(height), rd.nextInt(width), rd.nextInt(height));}//归还笔graphics.dispose();//写到流里面需要用到ImageIo//这里做的测试,在本地测试下是否画的是那回事/*try {ImageIO.write(image,"jpg",new FileOutputStream("E:/11.jpg"));} catch (IOException e) {e.printStackTrace();}*/this.bufferedImage = image;return image;}public static String getBase64(BufferedImage image) {String base64 = null;try {//输出流ByteArrayOutputStream stream = new ByteArrayOutputStream();ImageIO.write(image, "png", stream);base64 = Base64.encode(stream.toByteArray());log.info("生成的图片验证码base64:{}", base64);} catch (IOException e) {log.error("生成生成的图片验证码base64失败:{}", e.getMessage());e.printStackTrace();}return base64;}
}

4、前端发送 axios 请求 来获取 验证码

// 获取验证码getCode() {// 请求后台验证码throw axios.get("/captcha/getCaptcha",).then(res => {if (res.data.code === 0) {// 给 图片的 src 赋值this.codeImg = res.data.data.img;//  给 UUID 赋值this.imgUUID = res.data.data.imgUUID;//   this.code = res.data.data.code;console.log(this.code)} else {this.$message.error(res.data.msg)}}).catch(error => {alert("errorAjax")})
},

5、验证码的显示

<img :src="'data:image/gif;base64,'+ codeImg"
alt="验证码获取失败!" title="看不清?换一张!" class="codeImg"width="80%" @click="getCode()">

6、后端的处理

  @ApiOperation(value = "获取验证码")@GetMapping("/getCaptcha")@ResponseBodypublic Result getCaptcha() {//画图工具类CaptchaUtil imageCode = new CaptchaUtil();// 获取验证码对应的 base64  编码String base64 = CaptchaUtil.getBase64(imageCode.getImage());// 获取对应的 验证码 codeString code = imageCode.getCode();// 生成 UUIDString imgUUID = UUIDUtil.get32UUID();// 封装 获取的 验证码相关的数据 到 验证码对象中,并响应ImgResult imgResult = new ImgResult();imgResult.setImgUUID(imgUUID);imgResult.setImg(base64);imgResult.setCode(code);// 将验证码的信息保存到 redis中,并设置 有效时间2分钟!redisUtil.hset("captchaCache:", imgUUID, code, 120);// 将封装好的验证码对象响应给前端return Result.success(imgResult);}

UUID工具类如下:

package com.sany.crane.oa.common.util;import java.util.UUID;public class UUIDUtil {/*** 获得4个长度的十六进制的UUID** @return UUID*/public static String get4UUID() {UUID id = UUID.randomUUID();String[] idd = id.toString().split("-");return idd[1];}/*** 获得8个长度的十六进制的UUID** @return UUID*/public static String get8UUID() {UUID id = UUID.randomUUID();String[] idd = id.toString().split("-");return idd[0];}/*** 获得12个长度的十六进制的UUID** @return UUID*/public static String get12UUID() {UUID id = UUID.randomUUID();String[] idd = id.toString().split("-");return idd[0] + idd[1];}/*** 获得16个长度的十六进制的UUID** @return UUID*/public static String get16UUID() {UUID id = UUID.randomUUID();String[] idd = id.toString().split("-");return idd[0] + idd[1] + idd[2];}/*** 获得20个长度的十六进制的UUID** @return UUID*/public static String get20UUID() {UUID id = UUID.randomUUID();String[] idd = id.toString().split("-");return idd[0] + idd[1] + idd[2] + idd[3];}/*** 获得24个长度的十六进制的UUID** @return UUID*/public static String get24UUID() {UUID id = UUID.randomUUID();String[] idd = id.toString().split("-");return idd[0] + idd[1] + idd[4];}/*** 获得32个长度的十六进制的UUID** @return UUID*/public static String get32UUID() {UUID id = UUID.randomUUID();String[] idd = id.toString().split("-");return idd[0] + idd[1] + idd[2] + idd[3] + idd[4];}
}

前后端分离实现验证码相关推荐

  1. SpringBoot 前后端分离 实现验证码操作

    验证码的功能是防止非法用户恶意去访问登录接口而设置的一个功能,今天我们就来看看在前后端分离的项目中,SpringBoot 是如何提供服务的. 1|0SpringBoot 版本 本文基于的 Spring ...

  2. 基于前后端分离的验证码设计

    现在的web项目基本都是前后端分离的,后台只需要整理数据传给前端进行渲染就行. 验证码也是web中不可缺少的一部分,再以前的前后端不分离的场景中,一般是把图片以io流的方式传给前端,同时把内容存到se ...

  3. 若依前后端分离框架验证码的学习

    一.验证码的实现 1.1 前端部分 打开ruoyi-ui模块,在src/views/login.vue存放的就是若依框架的前端登录页面,在created()钩子函数里面有如下两个方法 跟踪进去红色箭头 ...

  4. 前后端分离php验证码

    <?php //必须至于顶部,多服务器端记录验证码信息,便于用户输入后做校验 session_start(); session_write_close(); $width = 65; $heig ...

  5. SpringBoot + Vue 开发前后端分离的旅游管理系统

    旅游管理系统 项目简介 项目演示 数据库建表 环境搭建 引入依赖(pom.xml) 配置文件(application.properties) href="javascript:;" ...

  6. 若依前后端分离版怎样去掉登录验证码

    场景 若依前后端分离版手把手教你本地搭建环境并运行项目: 若依前后端分离版手把手教你本地搭建环境并运行项目_BADAO_LIUMANG_QIZHI的博客-CSDN博客_若依前后端分离版本的配置 上面在 ...

  7. 前后端分离,SpringBoot如何实现验证码操作

    验证码的功能是防止非法用户恶意去访问登录接口而设置的一个功能,今天我们就来看看在前后端分离的项目中,SpringBoot是如何提供服务的. SpringBoot版本 本文基于的Spring Boot的 ...

  8. Spring Boot + Spring-Security实现前后端分离双重身份认证初学者指南(手机号密码JWT + 短信验证码)

    折(mo)腾(yu)了好几天,终于把双重身份认证实现了.(账号密码jwt+短信验证码) 看了很多视频,照葫芦画瓢敲了两三次,遇到各种各样的bug,比如循环依赖(通过@PostConstructor+s ...

  9. 不使用redis,在前后端分离项目的条件下将验证码进行储存

    前言: 近期项目进行了渗透测试,结果要求登录界面的验证码需有一次性使用.过期的功能. 小项目,也没必要为了个验证码使用redis,所以原有设想是将验证码储存在session中,但是前后端分离,项目又有 ...

最新文章

  1. Android10.0 四大组件与进程启动间关系
  2. angularjs 中的scope继承关系——(1)
  3. Oracle connet by prior 关键字的简单介绍和用法
  4. Java设计模式-中介者模式
  5. 想象中的同居生活 VS 真实的同居生活
  6. 前端学习(1133):正则表达式概述
  7. LInux:shell 彩色进度条实现(有图有代码有真相!!!)
  8. Rstudio更换主题/样式
  9. cocoscreator3d 模型透明_用 Cocos Creator 3D 实现小姐姐的发丝高光
  10. ?php echo $this_php如何使用echo输出常量+变量?
  11. hp服务器bios检测硬盘接口,惠普工作站UEFI BIOS如何检测硬盘
  12. 徒步运动软件怎么申请测试,徒步,不仅是体质健康的锻炼和检测,还是心理健康成长的过程...
  13. yum 碰到的问题与解决办法
  14. 虎虎生威年,用Compose Canvas画只猛虎让大家 “虎躯一震” 吧
  15. 与上司同事的谈话技巧
  16. Github每日精选(第56期):支持多语言的文字识别EasyOCR
  17. 有源带通滤波器快速实现
  18. 神经网络——实现MNIST数据集的手写数字识别
  19. 刚刚,马斯克当选美国工程院院士!智源张宏江博士入选外籍院士
  20. beam整合flink

热门文章

  1. Android 使用百度鹰眼实现运动轨迹功能
  2. Redis学习笔记记录1【图灵】
  3. element table 展开行 自定义展开方式与触发方式
  4. Delphi的方向?
  5. html5 模仿语音聊天气泡,CSS3 仿微信聊天小气泡实例代码
  6. 上市公司财务分析的主要方法
  7. Hbuilderx3.6.18连接逍遥模拟器
  8. python自学作业_python学习作业(一)
  9. grib1文件解析 python_关于解码grib1数据 变量的问题求教
  10. 战五渣系列之六(5分钟还搞不懂多线程?)