1、captcha
`captcha.js`是一个生成验证码的插件,使用js和canvas生成的,确保后端服务被暴力攻击,简单判断人机以及系统的安全性,体积小,功能多,支持配置。
验证码插件内容,包含一、验证码插件-使用,二、验证码插件栗子,三、API介绍,四、支持浏览器
注意:基于本项目源码从事科研、论文、系统开发,"最好"在文中或系统中代表来自于本项目的内容和创意,不然全部贡献者可能会鄙视你和你的项目。 使用本项目源码请尊重程序员职业和劳动
插件源码地址:https://github.com/saucxs/captchajavascript
文章首发地址:https://www.mwcxs.top/page/630.htmlhtml
2、功能
+ 版本v 1.0.0
- 一、支持随机字符内容配置,字符大小配置,字符类型配置,字符绘制方式配置,字符长度配置等
- 二、支持点位置随机,数量配置,点半径的配置
- 三、支持线条位置随机,宽度配置,线条数量的配置
- 四、支持随机前景色配置,区间值[0, 255],可使用默认值
- 五、支持随机背景色配置,区间值[0, 255],可使用默认值
- 六、支持点击更新视图
- 七、支持浏览器谷歌浏览器,火狐浏览器,Safari,IE10+等
3、验证码插件-使用
不依赖与其余的插件,实现起来很容易,`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'); });
4、原理
一、思路
如今咱们须要一个对象,而后调用对象的某个方法能够将验证码画出来。因此咱们须要一个构造函数,用来实例化对象。
function Regcode() {}
构造函数接受一些参数,用来定制验证码的点、线、字的各类属性(颜色、长短、大小等)。java
function Regcode(params = {}) { let p = Object.assign({...}, params); // 这里有定义好的属性和默认值 Object.keys(p).forEach(k => { // 将全部属性组合后添加到this上 this[k] = p[k]; }); }
二、draw方法git
首先咱们须要一个 draw 方法,做为验证码的绘制方法。程序员
draw 方法接收两个参数,canvas 的 dom 对象,用来建立绘图的2d对象。还须要一个回调函数 callback,用来接收每次绘制的文字。github
咱们把 draw 方法放在Regcode
的原型上,这样全部的实例对象均可以继承这些方法,而不是本身独立有一套。npm
在 draw 方法中,能够想到的是,咱们须要建立 canvas 的 2d对象,建立画布,而后开始依次绘制点、线、文字。canvas
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
(谷歌和火狐支持)来判断。可是这里由于要求不高,因此只是简单判断。后端
三、随机颜色数组
须要注意的是,在建立画布的时候,咱们使用了获取背景色的一个方法。在以前的需求中咱们能够看到,最高频的两个词是随机和颜色,因此确定是须要将这两个方法单独封装的。
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]); };
四、绘制线条
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(); // 进行绘制 } };
五、绘制圆点
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(); } };
六、绘制文字
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; };
绘制文字的时候,注意如下几点:
一、须要经过回调函数将当前绘制的文字输出。
二、须要指定文字的旋转角度、字体类型、文字颜色、绘制风格(填充或者不填充)。
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)插件,目前功能:图片打马赛克