js实现图形验证码

news2024/9/21 13:40:40

图形验证码起什么作用:

可以防止:恶意破解密码、刷票、论坛灌水,有效防止某个黑客对某一个特定注册用户用特定程序暴力破解方式进行不断的登录尝试。

验证码一般是防止批量注册的,人眼看起来都费劲,何况是机器。不少网站为了防止用户利用机器人自动注册、登录、灌水,都采用了验证码技术。所谓验证码,就是将一串随机产生的数字或符号,生成一幅图片, 图片里加上一些干扰。

例如随机画数条直线,画一些点(防止OCR),由用户肉眼识别其中的验证码信息,输入表单提交网站验证,验证成功后才能使用某项功能。

怎么实现图形验证码

原理:

1. 创建canvas元素,设置宽高等参数

2. 在canvas上绘制复杂的背景和前景噪点干扰线,增加识别难度

3. 随机生成数字/字母,通过旋转、移动、变形来绘制文本

4. 绘制完成后,把生成的验证码保存在实例的code属性中

5. 用户输入验证码与code属性中的值进行对比验证

6. 验证失败则重新生成验证码图形和code值

具体来看,主要步骤是:

  •  初始化时设置canvas参数,定义文本字符数组
  •  refresh方法用来生成验证码图形   - 绘制背景色和矩形框
  •                                                        - 随机生成文字,设置样式并旋转绘制
  •                                                        - 绘制干扰线和噪点
  • validate方法用来比对用户输入和验证码的值
  • 调用refresh重新生成验证码图形captcha的安全性就在于背景干扰线、噪点以及文字扭曲变形,使机器无法准确识别文字。同时验证码的值保存在内存中,不存入数据库,验证后即被清除,保证了每次都是新的验证码。这就是一个典型的前端图形验证码实现的基本流程和原理。可以根据需要对验证码样式、文字、长度等进行自定义。

代码:

html 

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title>图形验证码</title>
	</head>
	<style>
		#app{
			margin-top: 160px;
			width: 500px;
			height: 300px;
			display: flex;
			flex-direction: column;
			justify-content: center;
			align-items: center;
			border: 2px solid pink;
		}
		#my_body{
			width: 200px;
			display: flex;
			align-items: center;
			justify-content: space-between;
		}
		#code_input{
			width: 120px;
			height: 20px;
			line-height: 20px;
		}
		#code_input:focus {
			outline: 0;
		}
		#my_button{
			width: 50px;
			height: 24px;
		}
		#v_container{
			margin-bottom: 50px;
			width: 200px;
			height: 50px;
		}
	</style>
	<body>
		<div id="app">
			<div id="v_container" ></div>
			<div id="my_body">
				<input type="text" id="code_input" value="" placeholder="请输入验证码"/>
				<button id="my_button">验证</button>
			</div>
		</div>
	</body>
	<script src="gVerify.js"></script>
	<script>
		var verifyCode = new GVerify("v_container");
 
		document.getElementById("my_button").onclick = function(){
			var res = verifyCode.validate(document.getElementById("code_input").value);
			if(res){
				alert("验证正确");
			}else{
				alert("验证码错误");
			}
		}
	</script>
</html>

 js


!(function(window, document) {
	function GVerify(options) { //创建一个图形验证码对象,接收options对象为参数
		this.options = { //默认options参数值
			id: "", //容器Id
			canvasId: "verifyCanvas", //canvas的ID
			width: "100", //默认canvas宽度
			height: "30", //默认canvas高度
			type: "blend", //图形验证码默认类型blend:数字字母混合类型、number:纯数字、letter:纯字母
			code: ""
		}
		
		if(Object.prototype.toString.call(options) == "[object Object]"){//判断传入参数类型
			for(var i in options) { //根据传入的参数,修改默认参数值
				this.options[i] = options[i];
			}
		}else{
			this.options.id = options;
		}
		
		this.options.numArr = "0,1,2,3,4,5,6,7,8,9".split(",");
		this.options.letterArr = getAllLetter();
 
		this._init();
		this.refresh();
	}
 
	GVerify.prototype = {
		/**版本号**/
		version: '1.0.0',
		
		/**初始化方法**/
		_init: function() {
			var con = document.getElementById(this.options.id);
			var canvas = document.createElement("canvas");
			this.options.width = con.offsetWidth > 0 ? con.offsetWidth : "100";
			this.options.height = con.offsetHeight > 0 ? con.offsetHeight : "30";
			canvas.id = this.options.canvasId;
			canvas.width = this.options.width;
			canvas.height = this.options.height;
			canvas.style.cursor = "pointer";
			canvas.innerHTML = "您的浏览器版本不支持canvas";
			con.appendChild(canvas);
			var parent = this;
			canvas.onclick = function(){
				parent.refresh();
			}
		},
		
		/**生成验证码**/
		refresh: function() {
			this.options.code = "";
			var canvas = document.getElementById(this.options.canvasId);
			if(canvas.getContext) {
				var ctx = canvas.getContext('2d');
			}else{
				return;
			}
			
			ctx.textBaseline = "middle";
 
			ctx.fillStyle = randomColor(180, 240);
			ctx.fillRect(0, 0, this.options.width, this.options.height);
 
			if(this.options.type == "blend") { //判断验证码类型
				var txtArr = this.options.numArr.concat(this.options.letterArr);
			} else if(this.options.type == "number") {
				var txtArr = this.options.numArr;
			} else {
				var txtArr = this.options.letterArr;
			}
 
			for(var i = 1; i <= 4; i++) {
				var txt = txtArr[randomNum(0, txtArr.length)];
				this.options.code += txt;
				ctx.font = randomNum(this.options.height/2, this.options.height) + 'px SimHei'; //随机生成字体大小
				ctx.fillStyle = randomColor(50, 160); //随机生成字体颜色		
				ctx.shadowOffsetX = randomNum(-3, 3);
				ctx.shadowOffsetY = randomNum(-3, 3);
				ctx.shadowBlur = randomNum(-3, 3);
				ctx.shadowColor = "rgba(0, 0, 0, 0.3)";
				var x = this.options.width / 5 * i;
				var y = this.options.height / 2;
				var deg = randomNum(-30, 30);
				/**设置旋转角度和坐标原点**/
				ctx.translate(x, y);
				ctx.rotate(deg * Math.PI / 180);
				ctx.fillText(txt, 0, 0);
				/**恢复旋转角度和坐标原点**/
				ctx.rotate(-deg * Math.PI / 180);
				ctx.translate(-x, -y);
			}
			/**绘制干扰线**/
			for(var i = 0; i < 4; i++) {
				ctx.strokeStyle = randomColor(40, 180);
				ctx.beginPath();
				ctx.moveTo(randomNum(0, this.options.width), randomNum(0, this.options.height));
				ctx.lineTo(randomNum(0, this.options.width), randomNum(0, this.options.height));
				ctx.stroke();
			}
			/**绘制干扰点**/
			for(var i = 0; i < this.options.width/4; i++) {
				ctx.fillStyle = randomColor(0, 255);
				ctx.beginPath();
				ctx.arc(randomNum(0, this.options.width), randomNum(0, this.options.height), 1, 0, 2 * Math.PI);
				ctx.fill();
			}
		},
		
		/**验证验证码**/
		validate: function(code){
			var code = code.toLowerCase();
			var v_code = this.options.code.toLowerCase();
			console.log(v_code);
			if(code == v_code){
				return true;
			}else{
				this.refresh();
				return false;
			}
		}
	}
	/**生成字母数组**/
	function getAllLetter() {
		var letterStr = "a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z";
		return letterStr.split(",");
	}
	/**生成一个随机数**/
	function randomNum(min, max) {
		return Math.floor(Math.random() * (max - min) + min);
	}
	/**生成一个随机色**/
	function randomColor(min, max) {
		var r = randomNum(min, max);
		var g = randomNum(min, max);
		var b = randomNum(min, max);
		return "rgb(" + r + "," + g + "," + b + ")";
	}
	window.GVerify = GVerify;
})(window, document);

效果:

     

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

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

相关文章

让企业主们头疼的mkp勒索病毒,究竟有何来历,勒索病毒解密

mkp勒索病毒是一种比较常见的电脑病毒&#xff0c;它会对感染的电脑进行加密&#xff0c;并要求用户支付一定的赎金才能解锁。这种病毒已经引起了全球范围内的关注&#xff0c;因为它已经造成了严重的经济损失和电脑系统崩溃。 mkp勒索病毒是一种相对较新的病毒&#xff0c;但是…

【MySQL系列】索引的学习及理解

「前言」文章内容大致是MySQL索引的学习。 「归属专栏」MySQL 「主页链接」个人主页 「笔者」枫叶先生(fy) 目录 一、索引概念二、从硬件角度理解2.1 磁盘2.2 结论 三、从软件角度理解四、共识五、索引的理解5.1 一个现象和结论5.2 对Page进行建模5.3 索引可以采用的数据结构5.…

大数据组件Sqoop-安装与验证

&#x1f947;&#x1f947;【大数据学习记录篇】-持续更新中~&#x1f947;&#x1f947; 个人主页&#xff1a;beixi 本文章收录于专栏&#xff08;点击传送&#xff09;&#xff1a;【大数据学习】 &#x1f493;&#x1f493;持续更新中&#xff0c;感谢各位前辈朋友们支持…

NowCoder刷题 Python篇

NowCoder刷题 Python篇 Python入门 01 输入输出输入输出NP1 Hello World!NP2 多行输出NP3 读入字符串 01 输入输出 输入输出 NP1 Hello World! 参考代码&#xff1a; str Hello World! print(str)结果&#xff1a; NP2 多行输出 参考代码&#xff1a; str1 Hello World!…

上层应用开发与底层开发前途相比

底层开发和应用层开发都有自己的前途和发展方向&#xff0c;没有绝对的优劣之分。以下是对底层开发和应用层开发的一些观点&#xff1a;底层开发&#xff1a;优势&#xff1a;对计算机系统底层原理和技术有深入了解&#xff0c;能够进行系统级编程和优化&#xff0c;掌握底层技…

python爬虫—requests

一、安装 pip install requests 二、基本使用 1、基本使用 类型 &#xff1a; models.Response r.text : 获取网站源码 r.encoding &#xff1a;访问或定制编码方式 r.url &#xff1a;获取请求的 url r.content &#xff1a;响应的字节类型 r.status_code &#xff1a;响应…

在Mac终端使用unrar和rar 解压和压缩软件

1、首先从rarlab 网站下载 rar &#xff0f; unrar 工具 rarlab网站&#xff1a; https://www.rarlab.com/download.htm 2、解压缩下载的 tar.gz 压缩包&#xff08;rarmacos-x64-623.tar.gz&#xff09;&#xff0c;在下载目录downloads下自动创建一个rar的目录&#xff0c;其…

应用案例 | 基于三维机器视觉的机器人麻袋拆垛应用解决方案

​Part.1 项目背景 在现代物流和制造行业中&#xff0c;麻袋的拆垛操作是一个重要且频繁的任务。传统的麻袋拆垛工作通常由人工完成&#xff0c;分拣效率较低&#xff0c;人力成本较高&#xff0c;现场麻袋堆叠、变形严重&#xff0c;垛型不规则、不固定&#xff0c;严重影响分…

利用随机数生成猜数字游戏【C语言】

猜数字游戏实现 游戏要求生成随机数rand 函数srand 函数time 函数 确定生成随机数的范围猜数字游戏实现 游戏要求 自动生成随机数的范围&#xff1a;0-99玩家猜数字&#xff0c;猜数字的过程中&#xff0c;根据猜测数据的大小给出大了或小了的反馈&#xff0c;直到猜对&#x…

JavaScript Web APIs - 05 Window对象 、本地存储

Web APIs - 05 文章目录 Web APIs - 05js组成window对象定时器-延迟函数location对象navigator对象histroy对象本地存储&#xff08;今日重点&#xff09;localStorage&#xff08;重点&#xff09;sessionStorage&#xff08;了解&#xff09;localStorage 存储复杂数据类型 综…

unity面试题(基础篇)

事件函数的执行顺序 事件函数的执行顺序 - Unity 手册运行 Unity 脚本会按预定顺序执行大量事件函数。本页面将介绍这些事件函数,并说明它们的执行顺序。https://docs.unity.cn/cn/2019.4/Manual/ExecutionOrder.html 加载第一个场景 Awake:始终在任何 Start 函数之前并在实…

Linux(CentOS7)下如何配置多个Tomcat容器?

一、在 liunx 系统安装 jdk 1、安装jdk&#xff08;yum install 安装&#xff09; 查看是否系统是否自带jdk并卸载 rpm -qa |grep java rpm -qa |grep jdk rpm -qa |grep gcj 其中&#xff0c;GCJ是GNU的Java编译器,可以把java程序编译成本地代码&#xff0c;编译成功后的可…

Linux中安装MySQL5.7.42

1. 首先&#xff0c;下载mysql5.7.42的安装包&#xff08;下方是下载地址&#xff09;&#xff0c;选择红色框框的下载&#xff08;注意的是&#xff0c;这个链接只提供5.7的版本下载&#xff0c;可能还会更新&#xff0c;不一定打开就是5.7.42的版本&#xff0c;后续可能会有4…

坦克400 Hi4-T预售价28.5万元起,越野新能源好理解

8月25日&#xff0c;在以“智享蓉城&#xff0c;驭见未来”为主题的成都国际车展上&#xff0c;坦克品牌越野新能源再启新程&#xff0c;首次以全Hi4-T新能源阵容亮相展台&#xff0c;释放坦克品牌加速布局越野新能源的强烈信号。 Hi4-T架构首款落地车型坦克500 Hi4-T上市至今斩…

【C++入门】string类常用方法(万字详解)

目录 1.STL简介1.1什么是STL1.2STL的版本1.3STL的六大组件1.4STL的缺陷 2.string类的使用2.1C语言中的字符串2.2标准库中的string类2.3string类的常用接口说明 &#xff08;只讲解最常用的接口&#xff09;2.3.1string类对象的常见构造2.3.2 string类对象的容量操作2.3.3string…

stable diffusion实践操作-大模型介绍

本文专门开一节写大模型相关的内容&#xff0c;在看之前&#xff0c;可以同步关注&#xff1a; stable diffusion实践操作 常用到的基础模型和插件&#xff08;持续更新中&#xff09; 链接&#xff1a;https://pan.baidu.com/s/1c9utQmWlGcRqLTr_kftTyA?pwd1111 提取码&…

go语言配置

1、Go语言的环境变量 与Java等编程语言一样&#xff0c;安装Go语言开发环境需要设置全局的操作系统环境变量&#xff08;除非是用包管理工具直接安装&#xff09; 主要的系统级别的环境变量有两个: &#xff08;1&#xff09;GOROOT&#xff1a;表示Go语言环境在计算机上的安…

学习网络编程No.5【TCP套接字通信】

引言&#xff1a; 北京时间&#xff1a;2023/8/25/15:52&#xff0c;昨天刚把耗时3天左右的文章更新&#xff0c;充分说明我们这几天并不是在摆烂中度过&#xff0c;而是在为了更文不懈奋斗&#xff0c;历时这么多天主要是因为该部分知识比较陌生&#xff0c;所以需要我们花费…

行业追踪,2023-09-01

自动复盘 2023-09-01 凡所有相&#xff0c;皆是虚妄。若见诸相非相&#xff0c;即见如来。 k 线图是最好的老师&#xff0c;每天持续发布板块的rps排名&#xff0c;追踪板块&#xff0c;板块来开仓&#xff0c;板块去清仓&#xff0c;丢弃自以为是的想法&#xff0c;板块去留让…

云原生架构:在云环境中构建弹性应用

随着云计算技术的快速发展&#xff0c;云原生架构已经成为现代软件开发的热门话题。作为一种在云环境中构建和运行应用程序的方法论&#xff0c;云原生架构强调弹性、可扩展性和灵活性&#xff0c;使开发者能够更好地应对复杂的业务需求。本文将深入探讨云原生架构的核心概念、…