欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

简单字符验证码的实现

程序员文章站 2022-07-08 20:24:20
...

验证码的通用作用就是防止机器(爬虫)大规模的采集数据,防止不法分子通过抓包获取数据来模拟用户操作而产生危害用户的行为等。

为满足以上简单需求,首先验证码的字符不能放在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>
        )
    }