canvas画的验证码与loading

186 阅读3分钟

验证码

前端

说法一: 验证码是防机器的,防止恶意破解密码、刷票、论坛灌水、刷页。有效的防止某个黑客以特定程序暴力破解的方式进行不断的登录尝试。 一种常用的CAPTCHA测试是让用户输入一个扭曲变形的图片上所显示的文字或数字, 扭曲变形是为了避免被光学字符识别(OCR, Optical Character Recognition) 之类的电脑程序自动辨识出图片上的文数字而失去效果。由于这个测试是由计算机来考人类, 而不是标准图灵测试中那样由人类来考计算机,人们有时称CAPTCHA是一种反向图灵测试,

说法二: 首先,验证码的基本功能是进行人机识别,拦截机器行为。可以稍微细想一下,如果你们使用的方式, 自己都很容易就能抓取并识别,那就应该避免使用这种方式了。而且,现在图像识别技术也已经很先进了, 再加上打码平台的存在,单纯依靠验证码并不安全。如果对安全性有要求,同时也考虑用户体验的话, 建议使用行为验证,我们平时看到比较多的是滑动验证。行为验证是利用生物行为特征模型进行人机识别, 用在注册登录、防刷红包优惠券、防薅羊毛、数据反爬等各种调用接口的场景。 顶象的行为验证技术已经结合了设备指纹信息、IP/手机号风险、访问频率、地理位置等等的多维度信息, 判断更加精准。

后端

后端验证码是由后端生成的验证码。 当用户打开登录页面后,浏览器会向服务器发送请求并携带生成的令牌tolken,服务器随机生成验证码, 并将验证码和tolken的对应关系存储在redis缓冲中,之后会在前端动态的生成一张验证码图片。 当用户输入验证码并点击登录的时候,服务器会在redsi缓存中找到该浏览器的tolken对应的验证码, 验证验证码是否正确,如果正确,接下来开始比较用户名和密码。

功能原理分析: 如何实现验证码的随机性? 如何实现一块区域来展示验证码? 输入框的值和验证码值之间如何建立联系? 如何美化验证码UI,至少看起来得像吧 OK,带着这几个疑问,能搞清楚,基本就可以实现了 1----需要大量使用Math 方法 2----受到 echarts 和 百度地图这些 canvas库的启发,决定用canvas来实现,这样好理解,而且数据也好对应(关键是我只会canvas😩) 3----如果是Vue的话,就很简单,下面会详细说明, 如果是原生或者jQuery的话,可能在存验证码那里不像Vue那样优雅,仅此而已 4----我看了下别人写的验证码,至少得有 “倾斜”,“多余的线和点” 这几样,反正就是让你要仔细看才能看清楚的那种感觉,哈哈

验证码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title></title>
    <style>
        p{
            width: 400px;
            display: flex;
            justify-content: space-between;
            align-items: center;
            /* vertical-align: middle; */
        }
        label{
            height: 32px;
            line-height: 32px;
            display: inline-block;
        }
        .verification{
            border: none;
            border: 2px solid rgba(0,0,0,0.2);
            padding-left: 12px;
            height: 28px;
            border-radius: 5px;
        }
        .verification:focus{
            border: 2px solid rgba(41, 83, 250, 0.6);
            outline: aqua;
        }
        #canvas{
            border: 1px solid #ccc;
            cursor: pointer;
            border-radius: 5px;
            
        background: #e6ff8a;

        }
    </style>
</head>
<body>
    <form class="form">
        <p><label>验证:
            <input type="text" class="verification"  placeholder="请输入你的验证码">
        </label>
        <canvas width="130" height="32" id="canvas" onclick="handleCanvas()"></canvas>
        </p>
        
    </form>

    <script>
        let true_code="";
        let verification=document.getElementsByClassName("verification")[0].value;
        // let arr=[];
        
        function draw(){
            let arr=[];
            let w=document.getElementById("canvas").getAttribute("width");
            let h=document.getElementById("canvas").getAttribute("height");
            let canvas=document.getElementById("canvas");
            let ctx=canvas.getContext("2d");
            console.log(w,h);
            ctx.clearRect(0,0,w,h);
            ctx.beginPath();
            let code="abcdefghijklmnopqrstuvwxz";
            let c_code=code.toLocaleUpperCase();
            let num="012345789"
            let str=code.concat(c_code,num);
            str=[...str];
            // console.log(str);
            let length=str.length;
            // 四个验证码
            // console.log(arr);
            for(let i=0;i<4;i++){
                let num=Math.floor(Math.random()*length);
                let deg=(Math.random()*30*Math.PI)/180;
                let content=str[num];
                arr[i]=content;
                // arr[i]=content.toLocaleLowerCase();
                let x=10+i*20;
                let y=20+Math.random()*8;
                ctx.font= "bold 23px 微软雅黑";
                ctx.translate(x,y);
                ctx.rotate(deg);
                ctx.fillStyle=randomColor();
                ctx.fillText(content,0,0);  
                ctx.rotate(-deg);
                ctx.translate(-x,-y);

            }
            // console.log(arr);
            //六条线
            for(let i=0;i<=5;i++){
                ctx.strokeStyle=randomColor();
                ctx.beginPath();
                ctx.moveTo(Math.random()*w,Math.random()*h);
                ctx.lineTo(Math.random()*w,Math.random()*h);
                ctx.stroke();
            }
            //31个点
            for(let i=0;i<30;i++){
                ctx.strokeStyle=randomColor();
                ctx.beginPath();
                let x=Math.random()*w;
                let y=Math.random()*h;
                // console.log(x,y)
                ctx.moveTo(x,y);
                ctx.lineTo(x+1,y+1);
                
                ctx.stroke();
            }
            // console.log(arr);
            let count=0;
            for(let item of arr){
                if(isNaN(+item)!=true&&count<=1){
                    count++;
                    arr=arr;
                    break;
                }
            }
            // console.log(count==1);
            count==1?0:draw();
            // console.log(arr);
            true_code=arr.join("");
            // console.log(true_code);
        }
        
        function randomColor(){
            r=Math.round(Math.random()*255);
            g=Math.round(Math.random()*255);
            b=Math.round(Math.random()*255);
            return `rgb(${r},${g},${b})`;
        }

        function handleCanvas(){
            draw();
        }

        draw();
        
    </script>
</body>
</html>

loading


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <canvas width="200" height="200" id="myCanvas"></canvas>
    <script>
        function loading(){
            const canvas = document.getElementById("myCanvas");
            const ctx = canvas.getContext("2d");
            const w = canvas.getAttribute("width");
            const h = canvas.getAttribute("height");
            ctx.fillStyle="#fff";
            ctx.fillRect(0,0,200,200);
            let deg=0;
            let index=0;
            const draw=()=>{
                ctx.clearRect(0,0,200,200);
                for(let i=0;i<36;i++){
                    ctx.save();
                    ctx.beginPath();
                    ctx.translate(w/2,h/2);
                    ctx.rotate((deg*Math.PI)/100);
                    ctx.moveTo(0,0);
                    ctx.fillStyle=`rgba(24,144,255,${(1/36)*i})`;
                    ctx.arc(0,0,30,(i*10*Math.PI)/180,((i+2)*10*Math.PI)/180,false);
                    ctx.closePath();
                    ctx.fill();
                    ctx.restore();
                }
                ctx.save();
                ctx.beginPath();
                ctx.fillStyle="#fff";
                ctx.arc(w/2,h/2,20,0,(360*Math.PI)/180,false);
                ctx.fill();
                ctx.closePath();
                ctx.fill();
                ctx.restore();
                deg++;
                if(deg>=360){
                    deg=0;

                }
                requestAnimationFrame(draw);
            }
            draw();
        }
        loading();
    </script>
</body>
</html>