vue3 canvas verification code and slider puzzle verification

Human-computer 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:

  1. verify.js
// verify.js

function GVerify (options) {<!-- --> // Create a graphic verification code object and receive the options object as a parameter
    this.options = {<!-- --> //Default options parameter value
        id: "", // Container ID
        canvasId: "verifyCanvas", // ID of canvas
        width: "100", //Default canvas width
        height: "30", //Default canvas height
        type: "blend", //Default type of graphic verification code blend: mixed type of numbers and letters, number: pure numbers, letter: pure letters
        code: ""
    }

    if (Object.prototype.toString.call(options) == "[object Object]") {<!-- -->// Determine the type of the incoming parameter
        for (var i in options) {<!-- --> // Modify the default parameter value based on the parameters passed in
            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 number* */
    version: '1.0.0',

    /** Initialization method* */
    _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 = "Your browser version does not support canvas";
        con.appendChild(canvas);
        var parent = this;
        canvas.onclick = function () {<!-- -->
            parent.refresh();
        }
    },

    /** Generate verification code* */
    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") {<!-- --> // Determine the verification code type
            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'; // Randomly generate font size
            ctx.fillStyle = randomColor(50, 160); // Randomly generate font color
            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);
            /** Set the rotation angle and coordinate origin* */
            ctx.translate(x, y);
            ctx.rotate(deg * Math.PI / 180);
            ctx.fillText(txt, 0, 0);
            /** Restore the rotation angle and coordinate origin* */
            ctx.rotate(-deg * Math.PI / 180);
            ctx.translate(-x, -y);
        }
        /** Draw interference lines* */
        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();
        }
        /** Draw interference points* */
        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();
        }
    },

    /** Verify verification code* */
    validate: function (code) {<!-- -->
        var code = code.toLowerCase();
        var v_code = this.options.code.toLowerCase();
        if (code == v_code) {<!-- -->
            return true;
        } else {<!-- -->
            return false;
        }
    }
}

/** Generate an array of letters* */
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(",");
}

/** Generate a random number* */
function randomNum (min, max) {<!-- -->
    return Math.floor(Math.random() * (max - min) + min);
}

/** Generate a random color* */
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 box input content
const verifyValue = ref(null); // Verification code object instance

// Start verification
const startVerify = () => {<!-- -->
    if(inputCode.value.length < 4) return;
    const res = verifyValue.value.validate(inputCode.value);
    if (res) {<!-- -->
        alert('Verification passed');
    }
    verifyValue.value.refresh();
    inputCode.value = '';
}

onMounted(() => {<!-- -->
    verifyValue.value = new GVerify({<!-- -->
        id: "picyzm", // Area id for drawing verification code
        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:

Contains image svg, etc., has been uploaded to the github warehouse