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)插件,目前功能:圖片打馬賽克