基于canvas纯前端实现验证码的绘制

验证码功能是实现登录功能中比较常见的一个问题

验证码的整体思路是:

1.前端登录页面发起获取验证码图片请求.
2.服务端收到请求后,生成一个唯一id,对应的验证码图片 以及验证码图片对应的值(这个值使用缓存保存,id-值一一对应,缓存可使用redis或本地缓存,本地缓存适用于单节点服务)、然后把id
和图片返回前端.

3.前端收到id后保存到登录表单, 收到的图片直接展示到 登录页面

4.用户输入用户信息和 对应图片的验证码 和之前拿到的id发起登录请求

5.后端收到请求后,使用id获取缓存中真实的验证码值,然后和用户提交的验证码进行比较,如果相等则认为通过 反之不通过

后端可以采用开源工具类来生成验证码

在上面的整体逻辑中前端做的工作是比较少的,那么
如果想要实现纯前端实现验证码功能应该怎么写哪??
整体思路:

  1. 使用canvas绘制验证码
  2. 绘制的方法
    – 使用canvas的getContext方法获取到canvas标签及里面的内容
    – 使用canvas的fillStyle,fillRect, textBaseline, rotate,beginPath,arc,fill等方法进行绘制,对绘制的成功的文字进行平移,旋转,添加线条及点等方法实现干扰防止OCR

3.在进入页面的时候调用onMounted实现验证的渲染
4.给canvas添加点击事件实现当我点击图片的时候验证码的刷新操作

什么是OCR: 电子设备(例如扫描仪或数码相机)检查纸上打印的字符,通过检测暗、亮的模式确定其形状,然后用字符识别方法将形状翻译成计算机文字的过程

代码

<template><div><canvas ref="verify" @click="handleDraw" :width="state.width" :height="state.height"></canvas></div>
</template><script setup >
import { reactive, onMounted } from 'vue'
import { ref } from 'vue'
const verify = ref(null)
const state = reactive({pool: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890',// 声明两个变量存验证码的宽高width: 150,height: 45,// 验证码最终存储的位置imgCode: ''
})
// 初始化绘制图像验证码
onMounted(() => {state.imgCode = draw()})
// 点击之后重新绘制图形验证码
const handleDraw = () => {state.imgCode = draw()}
//生成随机数
const randomNum = (min, max) => {// parseInt(string, radix) 解析一个字符串并返回指定基数的十进制整数,radix 是 2-36 之间的整数,表示被解析字符串的基数return parseInt(Math.random() * (max - min) + min, 10)
}
// 随机生成颜色
const randomColor = (min, max) => {const r = randomNum(min, max)const g = randomNum(min, max)const b = randomNum(min, max)return `rgb(${r},${g},${b})`
}
// 实现验证码的绘制
const draw = () => {// ① 获取canvas属性const ctx = verify.value.getContext("2d")// ② 填充背景颜色ctx.fillStyle = randomColor(20, 256)ctx.fillRect(0, 0, state.width, state.height)   // ctx.fillRect(矩形起始点的x坐标,矩形起始点的y坐标,矩形的宽度,矩形的高度) fillRect()方法绘制一个填充了内容的矩形// fillText()  指定的坐标上绘制文本字符串,并使用当前的 fillStyle 对其进行填充// ③ 生成随机数,随机数旋转for (let i = 0; i < 4; i++) {const text = state.pool[randomNum(0, state.pool.length)]state.imgCode += textconsole.log('state.imgCode', state.imgCode)const fontSize = randomNum(16, 30)ctx.font = fontSize + "px Simhei"ctx.fillStyle = randomColor(0, 150) // 设置文字颜色ctx.textBaseline = "top"  // 述绘制文本时,当前文本基线的属性const deg = randomNum(-15, 15)  // 旋转的角度ctx.save()  // 保存当前的绘图状态ctx.translate((30 * i + 15), randomNum(10, 25)) // ctx.translate(x, y); x 点的水平方向、原始的 y 点垂直方向进行平移变换ctx.rotate((deg * Math.PI) / 180)  // Math.PI   3.14  【随机生成旋转角度】ctx.fillText(text, 0, 0)ctx.restore()  // ctx.restore() 方法后,会将绘图上下文恢复到最近一次保存的状态,也就是撤销之前的所有变换和样式设置,使得后续的绘制不受影响// 使用 save() 方法保存默认的状态,使用 restore() 进行恢复}// ④ 生成40个点和4条线形成干扰防止OCRfor (let i = 0; i < 5; i++) {ctx.beginPath()ctx.strokeStyle = randomColor(30, 256)ctx.moveTo(randomNum(0, state.width), randomNum(0, state.height))ctx.lineTo(randomNum(0, state.width), randomNum(0, state.height))ctx.fillStyle = randomColor(0, 150)ctx.stroke()  // 绘制线段}for (let x = 0; x < 40; x++) {ctx.beginPath()// ctx.arc( ①圆弧中心(圆心)的 x 轴坐标 ②圆弧中心(圆心)的 y 轴坐标 ③圆弧的半径 圆弧的起始点 ④x 轴方向开始计算,单位以弧度表示  ⑤圆弧的终点,单位以弧度表示)ctx.arc(randomNum(0, state.width), randomNum(0, state.height), 1, 0, 2 * Math.PI)ctx.closePath()// 笔点返回到当前子路径起始点的方法。它尝试从当前点到起始点绘制一条直线。如果图形已经是封闭的或者只有一个点,那么此方法不会做任何操作ctx.stroke()ctx.fillStyle = randomColor(150, 200)ctx.fill()}return state.imgCode
}
</script>

总结

前后端交互实现验证码功能:

即:
1) 进入页面的时候就会向后端发一个请求,请求包含

请求包含两个值
①图片
②存入缓存的key的值 key为uuid:value为验证码的答案)
【图片的字节码的编码----->后端画一个验证码的图传递给前端前端解析成图片】 (进入页面时,后端传验证码图片过来)

2)点击登录的时候会向后端传四个参数【用户名,密码,code(验证码答案),uuid (redis存的值(key值为uuid,value为验证码答案)】

取出uuid和code进行比较,一样的话就说明是你填的验证码对的,允许登录

纯前端实现验证码

基于canvas 实现绘制

参考

https://blog.csdn.net/MarkZQP/article/details/108222688
https://developer.mozilla.org/zh-CN/docs/Web/API/Canvas_API
https://blog.csdn.net/RequesToGod/article/details/121666622
https://www.cnblogs.com/loveCrane/p/17222671.html

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

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

相关文章

Python中的模块包第三方库详解

模块&包 模块 一个.py文件就是一个模块&#xff0c;里面是一些函数和变量&#xff0c;需要的时候可以导入。 模块命名规范: 1.以英文开头&#xff0c;不出现中文 2.模块名不应与系统内置函数重名 包 包本身就是一个文件夹&#xff0c;如果文件夹内有__init__.py文件&…

Java电梯模拟升级版

Java电梯模拟升级版 文章目录 Java电梯模拟升级版前言一、UML类图二、代码三、测试 前言 在上一版的基础上进行升级&#xff0c;楼层采用享元模式进行升级&#xff0c;并对楼层对象进一步抽象 一、UML类图 二、代码 电梯调度器抽象类 package cn.xx.evevator;import java.ut…

K倍区间 刷题笔记

法一 前缀和暴力搜索 &#xff08;数据大会超时&#xff09; #include<iostream> #include<cstring> #include<algorithm> #include<cstdio> using namespace std; const int N100010; int a[N],s[N]; int n,k; int main(){ cin>>n>>…

实现一个作用域插槽的场景

vue项目中&#xff0c;插槽slot有三种分别是&#xff1a;默认插槽、具名插槽、作用域插槽。默认插槽和具名插槽在平时的开发中用的比较多&#xff0c;作用域插槽用的相对较少&#xff0c;以前我对作用域插槽不是很理解&#xff0c;现在理解了一下。下面通过代码来实现一个作用域…

QLabel的setPixmap和setPicture有什么不同,请详细讲解

QLabel类提供了一个方便的方式来显示文本和图像。在Qt中&#xff0c;QLabel的setPixmap()和setPicture()方法都可以用来在标签中显示图像&#xff0c;但它们之间存在一些关键的区别&#xff0c;主要体现在它们接受的参数类型和用途上。 setPixmap() 参数类型&#xff1a;setP…

Linux系统之部署复古游戏平台

Linux系统之部署复古游戏平台 前言一、项目介绍1.1 项目简介1.2 项目特点1.3 游戏平台介绍二、本次实践介绍二、本地环境介绍2.1 本地环境规划2.2 本次实践介绍三、本地环境检查3.1 安装Docker环境3.2 检查Docker服务状态3.3 检查Docker版本3.4 检查docker compose 版本四、构建…

RISC-V架构学习资料整理

1、韦东山——D1S哪吒开发板的裸机代码仓库 https://github.com/bigmagic123/d1-nezha-baremeta 2、melis系统移植到D1S https://blog.51cto.com/u_13800193/6268813 3、韦东山的gitee仓库 https://gitee.com/weidongshan 4、D1S编译工具链下载 https://github.com/Tina-Linux/…

ModbusTcp协议

Modbus TCP是一种通信协议,用于工业设备之间的通信。它是Modbus协议家族中的一个成员,最初是为串行通信设计的,但后来扩展到了TCP/IP网络。Modbus TCP/IP是一种公开的标准,由Modbus组织制定,并且被广泛应用于工业自动化和楼宇自动化领域。 Modbus TCP的主要特点: 基于TC…

LabVIEW管道缺陷智能检测系统

LabVIEW管道缺陷智能检测系统 管道作为一种重要的输送手段&#xff0c;其安全运行状态对生产生活至关重要。然而&#xff0c;随着时间的推移和环境的影响&#xff0c;管道可能会出现老化、锈蚀、裂缝等多种缺陷&#xff0c;这些缺陷若不及时发现和处理&#xff0c;将严重威胁到…

Java将File转换为MultipartFile

MultipartFile 是 Java 中用于处理 HTTP 文件上传的一个接口。它通常与 Spring 框架一起使用&#xff0c;特别是在 Spring MVC 中&#xff0c;用于处理 multipart/form-data 类型的 HTTP 请求。当用户在网页表单中选择并上传文件时&#xff0c;服务器端的控制器方法可能会接收一…

ProxySQL实现mysql8主从同步读写分离

ProxySQL基本介绍 ProxySQL是 MySQL 的高性能、高可用性、协议感知代理。以下为结合主从复制对ProxySQL读写分离、黑白名单、路由规则等做些基本测试。 先简单介绍下ProxySQL及其功能和配置&#xff0c;主要包括&#xff1a; 最基本的读/写分离&#xff0c;且方式有多种&…

python基础训练-for循环

适应人群&#xff1a;学习python大概在10-20天&#xff0c;比较勤于动手的同学&#xff0c;比较混沌的新手可以手敲一遍下面这些for循环&#xff0c;在AI时代只有脑子智能&#xff0c;手不生疏&#xff0c;多多运用AI进行语义编程&#xff0c;看懂代码&#xff0c;通过openai教…

Java递归生成本地文件目录树形结构

Java递归生成本地文件目录(树行结构) 1.读取txt文件保存的文件目录结构 2.递归生成本地文件目录树形结构&#xff0c;并修改目录文件前缀进行递增 3.结果截图 4.代码 package com.zfi.server.device;import io.swagger.annotations.Api; import org.springframework.web.bind…

Postman接口测试—配置token为全局变量,配置测试环境

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 为什么要进行接口测试 因为不同端&#xff08;前段&#xff0c;后端&#xff09;的工作进度不一…

仿牛客网项目---关注模块的实现

本篇文章是关于我的项目的关注模块的开发。 关注模块的开发实现了用户之间的关注功能和关注列表的展示。通过使用相应的服务类处理关注和取消关注操作&#xff0c;并利用用户服务类获取用户信息&#xff0c;实现了关注功能的存储和查询。同时&#xff0c;通过触发关注事件&…

【软考】设计模式之访问者模式

目录 1. 说明2. 应用场景3. 结构图4. 构成5. java示例5.1 喂动物5.1.1 抽象访问者5.1.2 具体访问者5.1.3 抽象元素5.1.4 具体元素5.1.5 对象结构5.1.6 客户端类5.1.7 结果示例 5.2 超市销售系统5.2.1 业务场景5.2.2 业务需求类图5.2.3 抽象访问者5.2.4 具体访问者5.2.5 抽象元素…

前端面试拼图-原理源码

摘要&#xff1a;最近&#xff0c;看了下慕课2周刷完n道面试题&#xff0c;记录下... 1. JS内存泄漏如何检测&#xff1f;场景有哪些? 1.1 垃圾回收 GC 垃圾回收是一种自动管理内存的机制&#xff0c;它负责在运行时跟踪内存的分配和使用情况&#xff0c;并在不再需要的对象…

理解CAE

用于自监督表示学习的上下文自动编码器 摘要 我们提出了一种新的掩模图像建模(MIM)方法&#xff0c;上下文自编码器(CAE)&#xff0c;用于自监督表示预训练。我们通过在编码的表示空间中进行预测来预训练编码器。预训练任务包括两个任务:掩模表示预测—预测掩模块的表示&…

专业145+总分410+西工大西北工业大学827信号与系统考研经验电子信息与通信工程,海航,真题,大纲,参考书。

经过一年的努力&#xff0c;分数终于出来。今年专业课827信号与系统145&#xff08;很遗憾差了一点点满分&#xff0c;没有达到Jenny老师的最高要求&#xff09;&#xff0c;数一130&#xff0c;英语和政治也都比较平衡&#xff0c;总分410分&#xff0c;当然和信息通信考研Jen…

C及C++每日练习(2)

1.选择&#xff1a; 1.使用printf函数打印一个double类型的数据&#xff0c;要求&#xff1a;输出为10进制&#xff0c;输出左对齐30个字符&#xff0c;4位精度。以下哪个选项是正确的&#xff1f; A.%-30.4e B.%4.30e C.%-30.4f D.%-4.30 在上一篇文章中&#xff0c;提到了…