当前位置: 首页 > article >正文

浅谈 前端验证码那些事

浅谈 前端验证码那些事

背景

在实际项目的开发中,验证码的出现的频率相当高,它能实现人机甄别访问、减轻服务器负担的作用。常见的验证码为以下几类:

  1. 图形验证码:通过展示一个随机生成的图形,要求用户输入对应的文字或数字来判断用户是否为真实用户
  2. 滑块验证码:用户需要在一个包含滑块的图形上,通过滑动滑块到指定位置或者旋转某个图形直到合适的位置来完成验证
  3. 短信验证码:用户在注册或登录过程中输入手机号码,并请求发送验证码到手机,然后用户通过查看手机短信来获取验证码。
  4. 语音验证码:通过语音形式发送验证码到用户的手机或其他设备上,用户听取语音中的验证码后进行输入。主要用在视觉障碍用户或者在不方便查看图形验证码的用户
  5. 多种验证码相结合: 有些场景下,会将多种验证码相结合。如先通过图形验证码的测试,再进行短信验证码

其中短信验证码或者语音验证码一般都是直接购买第三方的服务来实现。

最后,采取哪种方式的验证码都是基于安全+体验+成功的综合考虑,合适的就是最好的。

图形验证码示例

随机文字

image-20240410091417228

点击图形文字

PixPin_2024-04-10_09-25-12

数学运算

image-20240410092618794

滑块验证码示例

普通滑块

recording

旋转图形

2024-04-10092146

短信验证码示例

image-20240410092644444

语音验证码示例

你输入号码后,就会有一个 PLJJ 给你打电话了。。。。

image-20240410092715881

多种验证码结合

recording

图形验证码实现流程

今天我们先来讲下相对简单的普通图形验证码

image-20240410091417228

我们以登录为背景

image-20240410100805863


泳道图

image-20240410094217427


  1. 前端:用户打开登录页面,发送请求,获取验证码
  2. 后端:接收请求,生成验证码(图片和具体文本),为了区分是当前用户的请求,一般会同时生成唯一 id
    1. 将验证码文本和唯一 id 存到服务端,如 redis,顺带存下时间,用来做验证码过期判断使用的
    2. 将验证码图片和唯一 id 响应给前端
  3. 前端:接收验证码图片和唯一 id,展示验证码图片
  4. 前端:将用户名、密码、用户输入的验证码和唯一 id 一并提交给后端
  5. 后端:接收数据,开始校验,并且返回校验结果

相关代码

前端使用的是 uniapp , 后端是配套的 uniapp 云开发环境。 如果想要一起交流 uniapp 相关知识,欢迎联系

前端登录页面

<template>
  <div class="login-container">
    <el-form
      ref="loginForm"
      class="login-form"
      autocomplete="on"
      label-position="left"
    >
      <div class="title-container">
        <h3 class="title">平台</h3>
      </div>

      <el-form-item prop="username">
        <el-input
          class="login-input"
          ref="username"
          placeholder="用户名"
          name="username"
          type="text"
          tabindex="1"
          autocomplete="on"
        />
      </el-form-item>

      <el-form-item prop="password">
        <el-input
          class="login-input"
          ref="password"
          placeholder="密码"
          name="password"
          tabindex="2"
          autocomplete="on"
        />
      </el-form-item>

      <el-form-item>
        <el-row :gutter="10" style="width:100%">
          <el-col :span="14">
            <el-input
              v-model="captcha"
              style="height: 100%;"
              placeholder="请输入验证码"
            />
          </el-col>
          <el-col :span="10">
            <div
              @click="getCaptcha"
              style="background-color: aliceblue;"
              v-html="captchaCode"
            ></div>
          </el-col>
        </el-row>
      </el-form-item>

      <el-button
        type="primary"
        style="width:100%;height:50px;margin-bottom:30px;"
        @click="valifyCaptcha"
        >登录</el-button
      >
    </el-form>
  </div>
</template>

<script setup>
import { ref } from "vue";
import { onLoad } from "@dcloudio/uni-app";

const captchaCloud = uniCloud.importObject("captcha"); // uniapp 的 云对象

const captchaCode = ref(""); // 展示验证码图片
const captcha = ref(""); // 记录用户输入的验证码
let uuid = ""; // 唯一id

// 获取验证码的
const getCaptcha = async () => {
  const res = await captchaCloud.getCaptcha();
  // console.log(res)
  captchaCode.value = res.svg;
  uuid = res.uuid;
};
// 单独校验验证码是否正确的 接口  用来测试使用  tips:本次没有校验用户名和密码
const valifyCaptcha = async () => {
  const res = await captchaCloud.valifyCaptcha(captcha.value, uuid);
  console.log(res);
};
onLoad(() => {
  getCaptcha();
});
</script>

<style lang="scss">
$bg: #2d3a4b;
$dark_gray: #889aa4;
$light_gray: #eee;

.login-container {
  width: 100%;
  background-color: $bg;
  overflow: hidden;
  height: 100vh;

  .login-form {
    position: relative;
    width: 520px;
    max-width: 100%;
    padding: 160px 35px 0;
    margin: 0 auto;
    overflow: hidden;

    :deep(.el-input__wrapper) {
      width: 100%;
      height: 100%;
      box-sizing: border-box;
    }
  }

  .title-container {
    position: relative;

    .title {
      font-size: 26px;
      color: $light_gray;
      margin: 0px auto 40px auto;
      text-align: center;
      font-weight: bold;
    }
  }
}

$bg: #283443;
$light_gray: #fff;
$cursor: #fff;

/* reset element-ui css */
.login-container {
  .el-input {
    display: inline-block;
    height: 47px;
  }

  .el-form-item {
    border: 1px solid rgba(255, 255, 255, 0.1);
    background: rgba(0, 0, 0, 0.1);
    border-radius: 5px;
    color: #454545;
  }
}
</style>

后端代码

使用的是 uniapp 云开发中的云对象, 示例代码 没有引入 redis ,直接存在数据库中。 生成验证码插件用的是 svg-captcha

"use strict";

const svgCaptcha = require("svg-captcha"); // 生成验证码的插件
const db = uniCloud.database();

module.exports = {
  _before: function () {
    // 通用预处理器
  },

  // 生成验证码
  async getCaptcha() {
    const captcha = svgCaptcha.create();

    // 成功插入数据库后,res会获得当前数据的id,将这个id 看成唯一id即可。 也可以使用第三方库  nanoid 独立生成
    const res = await db.collection("captcha").add({
      text: captcha.text,
      create_date: Date.now(),
    });
    // console.log(res)
    //返回数据给客户端
    return {
      svg: captcha.data,
      uuid: res.id,
    };
  },

  // 校验验证码
  async valifyCaptcha(text, uuid) {
    const dbJQL = uniCloud.databaseForJQL({
      // 获取JQL database引用,此处需要传入云对象的clientInfo
      clientInfo: this.getClientInfo(),
    });

    // 校验 唯一id和验证码和是否过期
    const res = await dbJQL
      .collection("captcha")
      .where(
        `text=='${text}' && ${Date.now()} - create_date > ${
          1000 * 60
        }  && _id=='${uuid}'`
      )
      .count();
    // console.dir(res)
    return !!res.total;
  },
};

http://www.kler.cn/a/451067.html

相关文章:

  • GTID下复制问题和解决
  • 第22天:信息收集-Web应用各语言框架安全组件联动系统数据特征人工分析识别项目
  • 基于卷积神经网络融合Inception模块的人脸识别
  • 【Object字段缺失】JS的对象在更新后发现Key值消失
  • 某科技局国产服务器PVE虚拟化技术文档
  • 编译原理复习---正则表达式+有穷自动机
  • STM32 与 AS608 指纹模块的调试与应用
  • keepalived踩坑记录
  • 前端:纯前端快速实现html导出word和pdf
  • 【EthIf-13】EthIfGeneral容器配置-01
  • IDEA使用Alt + Enter快捷键自动接受返回值一直有final修饰的问题处理
  • 重温设计模式--中介者模式
  • 微积分复习笔记 Calculus Volume 2 - 5.1 Sequences
  • Golang并发机制以及它所使⽤的CSP并发模型
  • [LeetCode-Python版]相向双指针——18. 四数之和
  • MySQL什么情况下会导致索引失效
  • 关于C语言库的调用
  • 如何编译Opencv +ffmpeg linux 明明安装了ffmpeg但是opencv就是找不到
  • Flutter 基础知识总结
  • vmime.net_4.dll详解:它是什么,有何用途?
  • 鸿蒙学习记录之http网络请求
  • Linux 环境下运行 .NET 8.0 core项目
  • 碰一碰发视频源码搭建的技术拓展,支持OEM
  • 【HarmonyOS 5.0】第十二篇-ArkUI公共属性(一)
  • QT程序发布后,mysql在其它电脑设备无法连接数据库
  • LLaMA-Factory(一)环境配置及包下载