vuejs3.0 从入门到精通——网页图形绘制:登录页面安全升级,JS动态生成图片验证码功能
网页图形绘制:登录页面安全升级,JS动态生成图片验证码功能
一、实验目标
- 掌握 Canvas 的基本用法。
- 掌握使用 Canvas 绘制文本的方法。
- 掌握使用 Canvas 绘制线段的方法。
- 掌握使用 Canvas 导出图片的方法。
- 掌握 JS 的基本语法和程序结构。
- 掌握 JS 函数的定义和应用。
- 掌握 JS 数组的定义和应用。
- 掌握 JS 面向对象编程方法。
- 掌握 JS DMO 操作。
- 综合应用 JS 编程技术和 Canvas 绘图,实现图片验证码功能。
二、实验任务
- 通过 JS 生成图片验证码。
- 使用 HTML5 编写登录页面并应用图片验证码。
三、设计思路
我们运用HTML5强大的Canvas元素,结合JavaScript脚本,精心绘制出一张富含随机文本、随机直线(干扰线)以及随机点(干扰点)的图片验证码。这一过程中,我们巧妙地借助了Math.random()函数,赋予图片验证码出色的随机性,使得每张验证码都独一无二,极大地提升了其安全性和防机器识别能力。这样的设计不仅保障了用户登录的安全性,也为用户带来了更流畅、更安全的登录体验。
四、实现实施(跟我做)
目录结构:
Jquery下载地址:https://code.jquery.com/jquery-3.6.1.min.js
4.1、步骤一:通过 JS 生成图片验证码
创建一个 JS 脚本,将其命名为 "verificationCode.js"。代码如下:
var nums = [ "1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "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", ]; var colors = [ "red", "blue", "green", "yellow", "orange", "purple", "pink", "brown", "gray", "black", "white", ]; var str = ""; //调用 drawCode()方法获取验证码,将验证码保存在全局变量 verVal 中 var verVal = drawCode(); //绘制验证码函数 function drawCode() { //获取 HTML 网页中的画布 var canvas = document.getElementById("verifyCanvas"); if (!canvas) { console.error("验证码画布元素不存在"); } else { //获取画布 2D 上下文 var context = canvas.getContext("2d"); //设置画布填充色 context.fillStyle = "white"; //清空画布 context.fillRect(0, 0, canvas.width, canvas.height); //设置字体和字号 context.font = "bold 30px 'Arial Black'"; //定义3个数组,用于存储坐标 var rand = new Array(); var x = new Array(); var y = new Array(); for (var i = 0; i < 4; i++) { rand.push(rand[i]); //这行代码将 rand 数组中当前索引 i 的元素添加到 rand 数组的末尾。 rand[i] = nums[Math.floor(Math.random() * nums.length)]; x[i] = i * 20 + 10; y[i] = Math.random() * 20 + 10; //设置字体颜色 context.fillStyle = colors[Math.floor(Math.random() * colors.length)]; //在指定位置上绘制文本 context.fillText(rand[i], x[i], y[i]); } //将数组转换为字符串并转换为大写形式 var str = rand.join("").toUpperCase(); //绘制 3条随机线 for (var i = 0; i < 3; i++) { //设置线条颜色 context.strokeStyle = colors[Math.floor(Math.random() * colors.length)]; //设置线条宽度 context.lineWidth = 1; //绘制一条随机线 context.beginPath(); context.moveTo( Math.floor(Math.random() * canvas.width), Math.floor(Math.random() * canvas.height) ); context.lineTo( Math.floor(Math.random() * canvas.width), Math.floor(Math.random() * canvas.height) ); context.stroke(); } //绘制 30个 随机点 for (var i = 0; i < 30; i++) { //设置点颜色 context.fillStyle = colors[Math.floor(Math.random() * colors.length)]; //绘制一个随机点 context.fillRect( Math.floor(Math.random() * canvas.width), Math.floor(Math.random() * canvas.height), 1, 1 ); } //绘制图片 convertCanvasToImage(canvas); return str; } } //绘制随机线函数 function drawline(canvas, context) { //设置路径起点 context.moveTo( Math.floor(Math.random() * canvas.width), Math.floor(Math.random() * canvas.height) ); //绘制直线路径 context.lineTo( Math.floor(Math.random() * canvas.width), Math.floor(Math.random() * canvas.height) ); //设置线条宽带 context.lineWidth = 0.25; //设置线条描边颜色 context.strokeStyle = "rgb(168,168,168,0.3)"; //对路径进行描边 context.stroke(); } // 绘制随机点函数 function drawDot(canvas, context) { // 根据画布的宽度生成一个随机整数作为x坐标 var px = Math.floor(Math.random() * canvas.width); // 根据画布的高度生成一个随机整数作为y坐标 var py = Math.floor(Math.random() * canvas.height); // 将画笔移动到指定的随机点位置 context.moveTo(px, py); // 从当前位置(即随机点)画一条到稍微偏离一点的线的终点,这里是为了形成一个点的效果 // 因为线的宽度是0.5,所以这样画出来的效果是一个小圆圈,看起来像是一个点 context.lineTo(px + 1, py + 1); // 设置线的宽度为0.5 context.lineWidth = 0.5; // 对之前定义的路径进行描边,也就是画出从moveTo到lineTo的那条小线段,从而形成一个点 context.stroke(); } //绘制图片函数 function convertCanvasToImage(canvas) { //隐藏画布 document.getElementById("verifyCanvas").style.display = "none"; var image = document.getElementById("code_img"); //将画布导出为图片,并设置图片的来源 URL image.src = canvas.toDataURL("image/png"); return image; } //单机图片刷新验证码 $("#code_img").click(function () { //移除画布 $("#verifyCanvas").remove(); //在 img 前面添加画布 $("#code_img").before( '<canvas id="verifyCanvas" width="100" height="40"></canvas>' ); //调用 drawCode()方法获取验证码,将验证码保存在全局变量 verVal 中 var verVal = drawCode(); });
4.2、步骤二:在登录页面中应用图片验证码
创建一个名为 login.html 的 HTML 静态网页,在该页面中创建一个登录表单,并通过 <script> 标签引入前面的 verificationCode.js 脚本文件,以添加图片验证码。创建 submit 事件处理程序,对输入的验证码进行检查,如果输入的验证码与图片验证码匹配,则允许登录,否则阻止登录。代码如下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>登录运维大模型后台管理平台</title> <style> .login-form { position: fixed; top: 50%; right: 13%; transform: translateY(-50%); width: 500px; height: 500px; max-width: 1000px; height: auto; display: flex; flex-direction: column; justify-content: center; align-items: flex-end; } .large-input { width: 450px; height: 50px; } .login-btn { position: fixed; width: 100px; height: 50px; right: 35%; background-color: #1890ff; border-radius: 30px; display: flex; justify-content: center; align-items: center; color: #fff; border: none; font-size: 18px; font-weight: bold; } .login-title { position: fixed; right: 10%; font-size: 30px; color: #090909; font-weight: bold; width: auto; max-width: 100%; height: auto; margin-bottom: 350px; } body { margin: 0; padding: 0; display: flex; justify-content: center; align-items: center; min-height: 100vh; background-color: #f0f2f5; } .form-item { display: flex; flex-direction: row; align-items: center; margin-bottom: 20px; } .form-label { width: 100px; /* 根据需要调整 label 的宽度 */ margin-right: 10px; /* 在 label 和 input 之间增加间距 */ } .form-item input[type="text"], .form-item input[type="password"] { flex-grow: 1; /* 让 input 根据剩余空间自适应宽度 */ margin-left: 0; /* 去除默认的左右间距 */ padding: 10px; } input[type="text"], input[type="password"] { width: 200px; height: 20px; padding: 10px; } .checkbox-label { display: inline-block; margin-left: 10px; } #code_img { cursor: pointer; margin-left: 10px; } button[type="submit"] { width: 100px; height: 50px; background-color: #1890ff; border-radius: 30px; color: #fff; border: none; font-size: 18px; font-weight: bold; cursor: pointer; margin-top: 20px; } </style> </head> <body> <div class="login-form"> <h2 class="login-title">登录运维大模型后台管理平台</h2> <form onsubmit="handleSubmit(event)"> <div class="form-item"> <label for="username" class="form-label">用户名:</label> <input type="text" id="username" placeholder="请输入邮箱/账号名/8位ID" required /> </div> <div class="form-item"> <label for="password" class="form-label">密码:</label> <input type="password" id="password" placeholder="请输入登录密码" required /> </div> <div class="form-item"> <label for="vcode" class="form-label">验证码:</label> <input type="text" id="vcode" placeholder="请输入验证码" required /> <canvas width="100" height="32" id="verifyCanvas"></canvas> <img id="code_img" title="单击刷新验证码" alt="vcode" /> </div> <div class="form-item"> <input type="checkbox" id="isRead" /> <label for="isRead" class="checkbox-label">《同意登录协议》</label> </div> <button type="submit" class="login-btn">登录</button> </form> </div> <script src="jquery-3.6.1.min.js"></script> <script src="verificationCode.js"></script> <script> function handleSubmit(event) { event.preventDefault(); // 阻止表单默认提交行为 const form = { username: document.getElementById("username").value, password: document.getElementById("password").value, vcode: document.getElementById("vcode").value.toUpperCase(), isRead: document.getElementById("isRead").checked, }; console.log(form); console.log(verVal); if (form.vcode !== verVal) { alert("输入的验证码错误"); document.getElementById("vcode").focus(); // 将焦点定位到验证码输入框 return false; } else { alert("登录成功"); // 实际情况下,这里会发起Ajax请求或执行其他登录逻辑 return true; } } </script> </body> </html>