captcha.js一个生成验证码的插件,使用js和canvas生成
一、captcha
`captcha.js`是一个生成验证码的插件,使用js和canvas生成的,确保后端服务被暴力攻击,简单判断人机以及系统的安全性,体积小,功能多,支持配置。 验证码插件内容,包含1、验证码插件-使用,2、验证码插件栗子,3、API介绍,4、支持浏览器 注意:基于本项目源码从事科研、论文、系统开发,"最好"在文中或系统中表明来自于本项目的内容和创意,否则所有贡献者可能会鄙视你和你的项目。 使用本项目源码请尊重程序员职业和劳动
插件源码地址:https://github.com/saucxs/captcha
文章首发地址:https://www.mwcxs.top/page/630.html
二、功能
+ 版本v 1.0.0
- 1、支持随机字符内容配置,字符大小配置,字符类型配置,字符绘制方式配置,字符长度配置等
- 2、支持点位置随机,数量配置,点半径的配置
- 3、支持线条位置随机,宽度配置,线条数量的配置
- 4、支持随机前景色配置,区间值[0, 255],可以使用默认值
- 5、支持随机背景色配置,区间值[0, 255],可以使用默认值
- 6、支持点击更新视图
- 7、支持浏览器谷歌浏览器,火狐浏览器,Safari,IE10+等 三、验证码插件-使用 不依赖与其他的插件,实现起来很容易,`captcha.js`是必须要引进的组件 3.1 本地引入封装的js文件 第一步:获取组件方式:`git clone https://github.com/saucxs/captcha.git` 第二步:clone后,在需要加验证码的相关页面引入验证码文件"captcha.js"以及准备好装验证码容器:
引入captcha内容
<script type="text/javascript" src="./captcha.js"></script>
装验证码的容器
<canvas width="240" height="90" id="captcha1"></canvas>
第三步:在确保页面DOM加载完毕之后,调用captcha的draw方法(手动加载):
/*不传值,统一走默认值*/
let captcha1 = new Captcha();
captcha1.draw(document.querySelector('#captcha1'), r => {
console.log(r, '验证码1');
});
/*传值,参数配置值,选择性配置*/
let captcha2 = new Captcha({
lineWidth: 1, //线条宽度
lineNum: 6, //线条数量
dotR: 2, //点的半径
dotNum: 25, //点的数量
preGroundColor: [10, 80], //前景色区间
backGroundColor: [150, 250], //背景色区间
fontSize: 30, //字体大小
fontFamily: ['Georgia', '微软雅黑', 'Helvetica', 'Arial'], //字体类型
fontStyle: 'stroke', //字体绘制方法,有fill和stroke
content: '一个验证码abcdefghijklmnopqrstuvw生成的插件使用的是canvas显示', //验证码内容
length: 6 //验证码长度
});
captcha2.draw(document.querySelector('#captcha2'), r => {
console.log(r, '验证码2');
});
使用插件的效果地址1:https://www.mwcxs.top/static/testTool/demo/index.html 3.2 npm包引入 第一步:npm获取验证码组件:
npm install captcha-mini
第二步:引入验证码模块:
import Captcha from 'captcha-mini'
或者
var Captcha = require("captcha-mini")
第三步:在确保页面DOM加载完毕之后,调用captcha的draw方法(手动加载):
/*不传值,统一走默认值*/
let captcha1 = new Captcha();
captcha1.draw(document.querySelector('#captcha1'), r => {
console.log(r, '验证码1');
});
/*传值,参数配置值,选择性配置*/
let captcha2 = new Captcha({
lineWidth: 1, //线条宽度
lineNum: 6, //线条数量
dotR: 2, //点的半径
dotNum: 25, //点的数量
preGroundColor: [10, 80], //前景色区间
backGroundColor: [150, 250], //背景色区间
fontSize: 30, //字体大小
fontFamily: ['Georgia', '微软雅黑', 'Helvetica', 'Arial'], //字体类型
fontStyle: 'stroke', //字体绘制方法,有fill和stroke
content: '一个验证码abcdefghijklmnopqrstuvw生成的插件使用的是canvas显示', //验证码内容
length: 6 //验证码长度
});
captcha2.draw(document.querySelector('#captcha2'), r => {
console.log(r, '验证码2');
});
四、原理 1、思路
现在我们需要一个对象,然后调用对象的某个方法可以将验证码画出来。所以我们需要一个构造函数,用来实例化对象。
function Regcode() {}
构造函数接受一些参数,用来定制验证码的点、线、字的各种属性(颜色、长短、大小等)。
function Regcode(params = {}) {
let p = Object.assign({...}, params); // 这里有定义好的属性和默认值
Object.keys(p).forEach(k => { // 将所有属性组合后添加到this上
this[k] = p[k];
});
}
2、draw方法
首先我们需要一个 draw 方法,作为验证码的绘制方法。
draw 方法接收两个参数,canvas 的 dom 对象,用来创建绘图的2d对象。还需要一个回调函数 callback,用来接收每次绘制的文字。
我们把 draw 方法放在Regcode
的原型上,这样所有的实例对象都可以继承这些方法,而不是自己独立有一套。
在 draw 方法中,可以想到的是,我们需要创建 canvas 的 2d对象,创建画布,然后开始依次绘制点、线、文字。
Regcode.prototype.draw = function(dom, callback = function () {}) { // 绘图
// 获取canvas dom
if (!this.paint) { // 如果没有2d对象,再进行赋值操作
this.canvas = dom; // 保存到this指针,方便使用
if (!this.canvas) return;
this.paint = this.canvas.getContext('2d'); // 保存到this指针,方便使用
if (!this.paint) return; // 回调函数赋值给this,方便使用
this.callback = callback;
}
// 随机画布颜色,使用背景色
let colors = this.getColor(this.backgroundColor);
this.paint.fillStyle = `rgba(${colors[0]}, ${colors[1]}, ${colors[2]}, 0.8)`;
// 绘制画布
this.paint.fillRect(0, 0, this.canvas.width, this.canvas.height);
// 绘图
this.arc();
this.line();
this.font();
};
需要简单判断一下是否有 dom 对象和2d对象,其实应该判断参数是否为 dom 对象,可以通过判断节点类型或者通过 dom instanceof HTMLElement
(谷歌和火狐支持)来判断。但是这里因为要求不高,所以只是简单判断。
3、随机颜色
需要注意的是,在创建画布的时候,我们使用了获取背景色的一个方法。在之前的需求中我们可以看到,最高频的两个词是随机和颜色,所以肯定是需要将这两个方法单独封装的。
Regcode.prototype.getColor = function(arr) { // 随机获取颜色
let colors = new Array(3).fill(''); // 创建一个长度为3的数组,值都填充为 ''
colors = colors.map(v => this.getRand(...arr)); // 每个成员随机获取一个强度值重组为新数组
return colors;
};
因为 rgb 颜色通常表示为 rgba(0,0,0,0.8)
,最后一位是透明度,这里没有参加随机。所以只考虑前3个数,在指定的强度区间内,只需要依次随机出3个数就好。所以在上面的方法中,还需要做的就是随机在一个数值区间中取值。
Regcode.prototype.getRand = function(...arr) { // 获取某个区间的随机数
arr.sort((a, b) => a - b); // 将传入的参数从小到大排序
return Math.floor(Math.random() * (arr[1] - arr[0]) + arr[0]);
};
4、绘制线条
Regcode.prototype.line = function() { // 绘制线条
for (let i = 0; i < this.lineNum; i++) {
// 随机获取线条的起止坐标
let x = this.getRand(0, this.canvas.width), y = this.getRand(0, this.canvas.height),
endx = this.getRand(0, this.canvas.width), endy = this.getRand(0, this.canvas.width);
this.paint.beginPath(); // 开始绘制
this.paint.lineWidth = this.lineWidth;
// 随机获取路径颜色
let colors = this.getColor(this.foregroundColor); // 使用前景色
this.paint.strokeStyle = `rgba(${colors[0]}, ${colors[1]}, ${colors[2]}, 0.8)`;
// 指定绘制路径
this.paint.moveTo(x, y);
this.paint.lineTo(endx, endy);
this.paint.closePath();
this.paint.stroke(); // 进行绘制
}
};
5、绘制圆点
Regcode.prototype.arc = function() { // 绘制圆点
for (let i = 0; i < this.dotNum; i++) {
// 随机获取圆心
let x = this.getRand(0, this.canvas.width), y = this.getRand(0, this.canvas.height);
this.paint.beginPath(); // 指定圆周路径
this.paint.arc(x, y, this.dotR, 0, Math.PI * 2, false);
this.paint.closePath(); // 随机获取路径颜色
let colors = this.getColor(this.foregroundColor);
this.paint.fillStyle = `rgba(${colors[0]}, ${colors[1]}, ${colors[2]}, 0.8)`; // 绘制
this.paint.fill();
}
};
6、绘制文字
acdefhijkmnpwxyABCDEFGHJKMNPQWXY12345789
,这里去掉了类似于字母 b 和 数字 6 这样的容易混淆的字符。)中,随机获取指定长度(允许通过参数自定义)的验证码。Regcode.prototype.getText = function() { // 随机获取验证码
let len = this.content.length, str = '';
for (let i = 0; i < this.len; i++) { // 随机获取每个因子,组成验证码
str += this.content[this.getRand(0, len)];
}
return str;
};
绘制文字的时候,注意以下几点:
1、需要通过回调函数将当前绘制的文字输出。
2、需要指定文字的旋转角度、字体类型、文字颜色、绘制风格(填充或者不填充)。
Regcode.prototype.font = function() { // 绘制文字
let str = this.getText(); // 获取验证码
this.callback(str); // 利用回调函数输出文字,用于与用户输入验证码进行比对
// 指定文字风格
this.paint.font = `${this.fontSize}px ${this.fontFamily}`;
this.paint.textBaseline = 'middle'; // 设置文本基线,middle是整个文字所占方框的高度的正中。
// 指定文字绘制风格
let fontStyle = `${this.fontStyle}Text`;
let colorStyle = `${this.fontStyle}Style`;
for (let i = 0; i < this.len; i++) { // 循环绘制每个字
let fw = this.paint.measureText(str[i]).width; // 获取文字绘制的实际宽度
// 获取每个字的允许范围,用来确定绘制单个文字的横坐标
let x = this.getRand(this.canvas.width / this.len * i, (this.canvas.width / this.len) * i + fw/2);
// 随机获取字体的旋转角度
let deg = this.getRand(-6, 6);
// 随机获取文字颜色
let colors = this.getColor(this.foregroundColor);
this.paint[colorStyle] = `rgba(${colors[0]}, ${colors[1]}, ${colors[2]}, 0.8)`;
// 开始绘制
this.paint.save();
this.paint.rotate(deg * Math.PI / 180);
this.paint[fontStyle](str[i], x, this.canvas.height / 2);
this.paint.restore();
}
};
基本上就完成了。
五、其他
欢迎使用[watermark-dom](https://github.com/saucxs/watermark-dom)插件,功能:给B/S网站系统加一个很浅的dom水印插件。
欢迎使用[captcha-mini](https://github.com/saucxs/captcha)插件,功能:生成验证码的插件,使用js和canvas生成的
欢迎使用[watermark-image](https://github.com/saucxs/watermark-image)插件,目前功能:图片打马赛克
captcha.js一个生成验证码的插件,使用js和canvas生成的更多相关文章
- js手机移动端选择插件 mobileSelect.js
一.mobileSelect获取方法 mobileSelect支持单选.多级联动.自定义回调函数.二次渲染.最新版本下载地址[2017-09-21更新]: https://github.com/onl ...
- JS+CSS3 360度全景图插件 - Watch3D.js
日常闲扯 从上一篇文章到这篇中间快过了一年了,时间真滴过得快.不是在下中间没想过写新的文章,而是自己确实变懒了(体重+1 +1 +1 +1....) ..OTL...不过到最后觉得还是需要写点东西,不 ...
- JS - 超强大文本动画插件Textillate.js
http://www.yyyweb.com/demo/textillate/ Textillate.js AsimplepluginforCSS3textanimations.
- Js 之常见手势操作插件 Hammer.js
一.下载 链接:https://pan.baidu.com/s/1UbEtSbT1xcmdzzTCaWmW1A提取码:ldqy 二.案例 三.代码 <!DOCTYPE html> < ...
- 第二百七十节,Tornado框架-生成验证码图片,以及验证码结合Session验证
Tornado框架-生成验证码图片,以及验证码结合Session验证 第一.生成验证码图片 生成验证码图片需要两个必须模块 1.python自带的random(随机模块) 2.Pillow()图像处 ...
- Js逆向-滑动验证码图片还原
本文列举两个例子:某象和某验的滑动验证 一.某验:aHR0cHM6Ly93d3cuZ2VldGVzdC5jb20vZGVtby9zbGlkZS1mbG9hdC5odG1s 未还原图像: 还原后的图: ...
- 使用.Net Core实现的一个图形验证码
SimpleCaptcha是一个使用简单,基于.Net Standard 2.0的图形验证码模块.它的灵感来源于Edi.Wang的这篇文章https://edi.wang/post/2018/10/1 ...
- python的random模块(生成验证码)
python的random模块(生成验证码) random模块常用方法 random.random() #生成0到1之间的随机数,没有参数,float类型 random.randint(1, 3) # ...
- 转: 通过Servlet生成验证码图片
孤傲苍狼 只为成功找方法,不为失败找借口! javaweb学习总结(九)—— 通过Servlet生成验证码图片 一.BufferedImage类介绍 生成验证码图片主要用到了一个BufferedIma ...
随机推荐
- Java面向对象进阶篇(内部类)
一. 概念 大部分时候,类被定义成一个独立的程序单元.有时候把一个类放在另一个类内部定义,这个类被称为内部类,包含内部类的类也被称为外部类. 内部类的主要作用: 内部类提供良好的封装,可以把内部类隐藏 ...
- [Python学习之路] 猜大小游戏
# coding =utf-8 import random def roll_dice(number=3, points=None): if points == None: points = [] w ...
- cocos2d-x_ Windows下Android环境搭建
在Windows环境下编译cocos2d-x-3.0 Android-NDK编译:cocos2d-x(二) Mac 下搭建:http://www.cocoachina.com/bbs/read.php ...
- .NET开发微信小程序-获取OpenId
注:获取当前用户信息只需要用GetUserInfo这个方法就行.这里就不需要提了 前端代码: CallBack:回调函数 function GetOpenID(CallBack){ var appIn ...
- react native 1跳2 2跳3 3跳4 4pop回2
网上有介绍导航的很多了 就不一一说了 直接说一个小功能 popToRoute pop回指定页面 第一次写 组织能力不是特别好 直接贴代码 例如 我们有四个页面 从第四个pop到第二个页面 先 ...
- 使用crypto-js对数据进行AES加密、解密
前段时间做项目有用到数据加密,前端加密,后端解密(前端也可以解密),话不多说进入正题: 第一步: npm i crypto-js -S 第二步: 在需要加密或解密的地方引入crypto-js: imp ...
- debain 安装nodejs
apt-get update -yapt-get install -y build-essential curl curl -sL https://deb.nodesource.com/setup_8 ...
- Boyer-Moore(BM)算法,文本查找,字符串匹配问题
KMP算法的时间复杂度是O(m + n),而Boyer-Moore算法的时间复杂度是O(n/m).文本查找中“ctrl + f”一般就是采用的BM算法. Boyer-Moore算法的关键点: 从右遍历 ...
- springboot之启动原理解析
前言 SpringBoot为我们做的自动配置,确实方便快捷,但是对于新手来说,如果不大懂SpringBoot内部启动原理,以后难免会吃亏.所以这次博主就跟你们一起一步步揭开SpringBoot的神秘面 ...
- 外观模式facade
一句话,多外呈现一个统一接口,内部的具体实现不关心. 外观模式facade,其实就是在调用者 与 被调用的实现层 之间加一层 facade层,不管内部如何实现, 用什么技术 方法实现,对外呈现的外观是 ...