vue3 canvas verification code and slider puzzle verification

Human-machine authentication

Adding human-machine authentication in some resource downloading and reading scenarios can prevent some simple network attacks. Only two native implementations are introduced.


canvas verification code

Draw specific text through canvas and mix it with lines and colors.

Rendering:
Insert image description here

  1. verify.js
// verify.js

function GVerify (options) {
    
     // 创建一个图形验证码对象,接收options对象为参数
    this.options = {
    
     // 默认options参数值
        id: "", // 容器Id
        canvasId: "verifyCanvas", // canvas的ID
        width: "100", // 默认canvas宽度
        height: "30", // 默认canvas高度
        type: "blend", // 图形验证码默认类型blend:数字字母混合类型、number:纯数字、letter:纯字母
        code: ""
    }

    if (Object.prototype.toString.call(options) == "[object Object]") {
    
    // 判断传入参数类型
        for (var i in options) {
    
     // 根据传入的参数,修改默认参数值
            this.options[i] = options[i];
        }
    } else {
    
    
        this.options.id = options;
    }

    this.options.numArr = "0,1,2,3,4,5,6,7,8,9".split(",");
    this.options.letterArr = getAllLetter();

    this._init();
    this.refresh();
}

GVerify.prototype = {
    
    
    /** 版本号* */
    version: '1.0.0',

    /** 初始化方法* */
    _init: function () {
    
    
        var con = document.getElementById(this.options.id);
        var canvas = document.createElement("canvas");
        this.options.width = con.offsetWidth > 0 ? con.offsetWidth : "100";
        this.options.height = con.offsetHeight > 0 ? con.offsetHeight : "30";
        canvas.id = this.options.canvasId;
        canvas.width = this.options.width;
        canvas.height = this.options.height;
        canvas.style.cursor = "pointer";
        canvas.innerHTML = "您的浏览器版本不支持canvas";
        con.appendChild(canvas);
        var parent = this;
        canvas.onclick = function () {
    
    
            parent.refresh();
        }
    },

    /** 生成验证码* */
    refresh: function () {
    
    
        this.options.code = "";
        var canvas = document.getElementById(this.options.canvasId);
        if (canvas.getContext) {
    
    
            var ctx = canvas.getContext('2d');
        } else {
    
    
            return;
        }

        ctx.textBaseline = "middle";

        ctx.fillStyle = randomColor(180, 240);
        ctx.fillRect(0, 0, this.options.width, this.options.height);

        if (this.options.type == "blend") {
    
     // 判断验证码类型
            var txtArr = this.options.numArr.concat(this.options.letterArr);
        } else if (this.options.type == "number") {
    
    
            var txtArr = this.options.numArr;
        } else {
    
    
            var txtArr = this.options.letterArr;
        }

        for (var i = 1; i <= 4; i++) {
    
    
            var txt = txtArr[randomNum(0, txtArr.length)];
            this.options.code += txt;
            ctx.font = randomNum(this.options.height / 2, this.options.height) + 'px SimHei'; // 随机生成字体大小
            ctx.fillStyle = randomColor(50, 160); // 随机生成字体颜色
            ctx.shadowOffsetX = randomNum(-3, 3);
            ctx.shadowOffsetY = randomNum(-3, 3);
            ctx.shadowBlur = randomNum(-3, 3);
            ctx.shadowColor = "rgba(0, 0, 0, 0.3)";
            var x = this.options.width / 5 * i;
            var y = this.options.height / 2;
            var deg = randomNum(-30, 30);
            /** 设置旋转角度和坐标原点* */
            ctx.translate(x, y);
            ctx.rotate(deg * Math.PI / 180);
            ctx.fillText(txt, 0, 0);
            /** 恢复旋转角度和坐标原点* */
            ctx.rotate(-deg * Math.PI / 180);
            ctx.translate(-x, -y);
        }
        /** 绘制干扰线* */
        for (var i = 0; i < 4; i++) {
    
    
            ctx.strokeStyle = randomColor(40, 180);
            ctx.beginPath();
            ctx.moveTo(randomNum(0, this.options.width), randomNum(0, this.options.height));
            ctx.lineTo(randomNum(0, this.options.width), randomNum(0, this.options.height));
            ctx.stroke();
        }
        /** 绘制干扰点* */
        for (var i = 0; i < this.options.width / 4; i++) {
    
    
            ctx.fillStyle = randomColor(0, 255);
            ctx.beginPath();
            ctx.arc(randomNum(0, this.options.width), randomNum(0, this.options.height), 1, 0, 2 * Math.PI);
            ctx.fill();
        }
    },

    /** 验证验证码* */
    validate: function (code) {
    
    
        var code = code.toLowerCase();
        var v_code = this.options.code.toLowerCase();
        if (code == v_code) {
    
    
            return true;
        } else {
    
    
            return false;
        }
    }
}

/** 生成字母数组* */
function getAllLetter () {
    
    
    var letterStr = "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";
    return letterStr.split(",");
}

/** 生成一个随机数* */
function randomNum (min, max) {
    
    
    return Math.floor(Math.random() * (max - min) + min);
}

/** 生成一个随机色* */
function randomColor (min, max) {
    
    
    var r = randomNum(min, max);
    var g = randomNum(min, max);
    var b = randomNum(min, max);
    return "rgb(" + r + "," + g + "," + b + ")";
}

export default GVerify;
  1. Introduce verify.js into the component and initialize it (vue3)
<template>
    <div class="verify">
        <p id="picyzm"/>
        <input type="text" v-model="inputCode" ref="inputRef" autofocus @keyup="startVerify"/>
    </div>
</template>

<script setup>
import {
      
       ref, onMounted } from 'vue';
import GVerify from './verify';

const inputCode = ref(''); // input框输入内容
const verifyValue = ref(null); // 验证码对象实例

// 开始验证
const startVerify = () => {
      
      
    if(inputCode.value.length < 4) return;
    const res = verifyValue.value.validate(inputCode.value);
    if (res) {
      
      
        alert('校验通过');
    }
    verifyValue.value.refresh();
    inputCode.value = '';
}

onMounted(() => {
      
      
    verifyValue.value = new GVerify({
      
      
        id: "picyzm", // 绘制验证码的区域id
        type: "blend"
    });
})
</script>

<style lang='scss' scoped>
.verify {
      
      
    display: flex;
    align-items: center;

    p {
      
      
        width: 100px;
        height: 30px;
        border: 1px solid #8b79ec;
        margin-right: 10px;
    }

    input {
      
      
        width: 80px;
        height: 30px;
        border-radius: 8px;
        border: 1px solid #ccc;
        outline: none;
        font-size: 12px;
        text-indent: 10px;
        letter-spacing: 2px;
        box-sizing: border-box;
    }
}
</style>



Image slider verification code

Different shapes are cut out by cutting out two identical canvases, one is cut into a puzzle piece, and the other is cut into a background without a puzzle piece, and then shifted.

When the user drags the slider, the two canvases are actually overlapped, and the puzzle will naturally align with the blank area of ​​​​the background.

Rendering:
Insert image description here
Insert image description here

Contains pictures, svg, etc., has been uploaded to github warehouse

Guess you like

Origin blog.csdn.net/Raccon_/article/details/134014619