簡單字符驗證碼的實現

驗證碼的通用作用就是防止機器(爬蟲)大規模的採集數據,防止不法分子通過抓包獲取數據來模擬用戶操作而產生危害用戶的行爲等。

爲滿足以上簡單需求,首先驗證碼的字符不能放在html標籤裏面,這可以被爬蟲直接獲取,因此採用canvas來繪製。爲增加爬蟲識別難度,對字符進行一定程度是旋轉,添加干擾線和干擾點。(雖然以現在機器學習的能力這些別沒有什麼卵用,但簡單的驗證碼都是這麼做的,考慮更爲安全的方式可以選擇圖形驗證或者短信驗證)

代碼(react

import React, {useEffect} from 'react';
import styles from './verification-code.scss';

useEffect(() => {
        init()
    }, [])

const init = () => {
        const canvas  = document.getElementById('verificationCode');
        const ctx = canvas.getContext('2d');
        // 隨機獲取4位字符數組
        let code = getVerificationCode(4);
        // 填充背景
        ctx.fillStyle = '#ddd';
        ctx.fillRect(0, 0, 80, 30);
        // 繪製干擾線
        for(var i = 0; i < 4; i++) {
            ctx.strokeStyle = randomColor();
            ctx.beginPath();
            ctx.moveTo(randomNum(0, canvas.width), randomNum(0, canvas.height));
            ctx.lineTo(randomNum(0, canvas.width), randomNum(0, canvas.height));
            ctx.stroke();
        // 繪製干擾點
        for(var i = 0; i < canvas.width/4; i++) {
            ctx.fillStyle = randomColor();
            ctx.beginPath();
            ctx.arc(randomNum(0, canvas.width), randomNum(0, canvas.height), 1, 0, 2 * Math.PI);
            ctx.fill();
        }
        code.foreach((item, index) => {
            ctx.font = '20px serif';
            // 隨機顏色
            ctx.fillStyle = randomColor();
            // 隨機旋轉
            let rotate = index & 1 
                            ? Math.random() * Math.PI / 20
                            : - Math.random() * Math.PI / 20;
            ctx.rotate(rotate);
            ctx.translate(15, 0);
            ctx.fillText(item, 0, 23);
        })

        // 隨機獲取指定長度字符數組
        const getVerificationCode = (len) => {
            let randomStr = '0,1,2,3,4,5,6,7,8,9,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';
            let randomArr = randomStr.split(',');

            let code = [];
            for(let i=0; i<len; i++) {
                code.push(randomArr[Math.floor(Math.random()*62)])
            }
            return code
        }
        // 隨機獲取顏色
        const randomColor = () => {
            return `rgb(${85 * randomNum(0, 3)}, ${255 - 85 * randomNum(0, 3)}, ${85 * randomNum(0, 3)})`
        }
        // 隨機獲取指定範圍內整數
        const randomNum = (start, end) => {
            if(end <= start) {
                return;
            }
            return start + Math.floor(Math.random() * (end - start));
        }
        return (
            <div className={styles.wrap}>
                <canvas id='verificationCode' width='80px' height='30px'></canvas>
            </div>
        )
    }
               
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章