vuejs3.0 从入门到精通——网页图形绘制:登录页面安全升级,JS动态生成图片验证码功能

网页图形绘制:登录页面安全升级,JS动态生成图片验证码功能

一、实验目标

  1. 掌握 Canvas 的基本用法。
  2. 掌握使用 Canvas 绘制文本的方法。
  3. 掌握使用 Canvas 绘制线段的方法。
  4. 掌握使用 Canvas 导出图片的方法。
  5. 掌握 JS 的基本语法和程序结构。
  6. 掌握 JS 函数的定义和应用。
  7. 掌握 JS 数组的定义和应用。
  8. 掌握 JS  面向对象编程方法。
  9. 掌握 JS DMO 操作。
  10. 综合应用 JS 编程技术和 Canvas 绘图,实现图片验证码功能。

二、实验任务

  1. 通过 JS 生成图片验证码。
  2. 使用 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>

4.3、步骤三:测试图片验证码

posted @ 2024-04-07 11:14  左扬  阅读(144)  评论(0编辑  收藏  举报
levels of contents