前端实现验证码功能

需求

前端实现验证码功能
在这里插入图片描述

分析

1. 输入验证

在这里插入图片描述

  • dentify.vue
<template>
  <div class="s-canvas">
    <canvas
      id="s-canvas"
      :width="contentWidth"
      :height="contentHeight"
    ></canvas>
  </div>
</template>
<script>
export default {
  name: "SIdentify",
  props: {
    identifyCode: {
      // 默认注册码
      type: String,
      default: "1234",
    },
    fontSizeMin: {
      // 字体最小值
      type: Number,
      default: 25,
    },
    fontSizeMax: {
      // 字体最大值
      type: Number,
      default: 35,
    },
    backgroundColorMin: {
      // 验证码图片背景色最小值
      type: Number,
      default: 200,
    },
    backgroundColorMax: {
      // 验证码图片背景色最大值
      type: Number,
      default: 220,
    },
    dotColorMin: {
      // 背景干扰点最小值
      type: Number,
      default: 60,
    },
    dotColorMax: {
      // 背景干扰点最大值
      type: Number,
      default: 120,
    },
    contentWidth: {
      // 容器宽度
      type: Number,
      default: 90,
    },
    contentHeight: {
      // 容器高度
      type: Number,
      default: 38,
    },
  },
  methods: {
    // 生成一个随机数
    randomNum(min, max) {
      return Math.floor(Math.random() * (max - min) + min);
    },

    // 生成一个随机的颜色
    randomColor(min, max) {
      let r = this.randomNum(min, max);
      let g = this.randomNum(min, max);
      let b = this.randomNum(min, max);
      return "rgb(" + r + "," + g + "," + b + ")";
    },
    //画图
    drawPic() {
      let canvas = document.getElementById("s-canvas");
      //创建一个2D对象作为上下文。
      let ctx = canvas.getContext("2d");
      ctx.textBaseline = "bottom";
      // 绘制背景
      ctx.fillStyle = "#e6ecfd";
      ctx.fillRect(0, 0, this.contentWidth, this.contentHeight);
      // 绘制文字
      for (let i = 0; i < this.identifyCode.length; i++) {
        this.drawText(ctx, this.identifyCode[i], i);
      }
      this.drawLine(ctx);
      this.drawDot(ctx);
    },
    //在画布上显示数据
    drawText(ctx, txt, i) {
      ctx.fillStyle = this.randomColor(50, 160); // 随机生成字体颜色
      ctx.font =
        this.randomNum(this.fontSizeMin, this.fontSizeMax) + "px SimHei"; // 随机生成字体大小
      let x = (i + 1) * (this.contentWidth / (this.identifyCode.length + 1));
      let y = this.randomNum(this.fontSizeMax, this.contentHeight - 5);
      var deg = this.randomNum(-30, 30);
      // 修改坐标原点和旋转角度
      ctx.translate(x, y);
      ctx.rotate((deg * Math.PI) / 180);
      ctx.fillText(txt, 0, 0);
      // 恢复坐标原点和旋转角度
      ctx.rotate((-deg * Math.PI) / 180);
      ctx.translate(-x, -y);
    },

    // 绘制干扰线
    drawLine(ctx) {
      for (let i = 0; i < 4; i++) {
        ctx.strokeStyle = this.randomColor(100, 200);
        ctx.beginPath();
        ctx.moveTo(
          this.randomNum(0, this.contentWidth),
          this.randomNum(0, this.contentHeight)
        );
        ctx.lineTo(
          this.randomNum(0, this.contentWidth),
          this.randomNum(0, this.contentHeight)
        );
        ctx.stroke();
      }
    },

    // 绘制干扰点
    drawDot(ctx) {
      for (let i = 0; i < 30; i++) {
        ctx.fillStyle = this.randomColor(0, 255);
        ctx.beginPath();
        ctx.arc(
          this.randomNum(0, this.contentWidth),
          this.randomNum(0, this.contentHeight),
          1,
          0,
          2 * Math.PI
        );
        ctx.fill();
      }
    },
  },
  watch: {
    identifyCode() {
      this.drawPic();
    },
  },
  mounted() {
    this.drawPic();
  },
};
</script>
  • index.vue
<template>
  <div class="home">
    <el-row>
      <el-col :span="4"
        ><el-input
          placeholder="请输入验证码"
          v-model="formLogin.code"
        ></el-input
      ></el-col>
      <el-col :span="4">
        <div class="login-code" width="100%" @click="refreshCode">
          <!--验证码组件-->
          <dentify :identifyCode="identifyCode"></dentify></div
      ></el-col>
    </el-row>
    <div><el-button @click="submit">提交</el-button></div>
  </div>
</template>

<script>
import dentify from "./dentify";
export default {
  name: "HomeView",
  components: {
    dentify,
  },
  data() {
    return {
      // 表单提交内容
      formLogin: {
        code: "", //验证码输入框
      },
      identifyCodes: "1234567890abcdefjhijklinopqrsduvwxyz", //随机串内容,从这里随机抽几个显示验证码
      identifyCode: "", //验证码图片内容
    };
  },
  mounted() {
    // 初始化验证码
    this.identifyCode = "";
    //参数:(1)随机串内容。(2)验证码显示位数
    this.makeCode(this.identifyCodes, 4);
  },
  methods: {
    // 重置验证码
    refreshCode() {
      this.identifyCode = "";
      this.makeCode(this.identifyCodes, 4);
    },
    //获取验证码的值
    makeCode(o, l) {
      for (let i = 0; i < l; i++) {
        //通过循环获取字符串内随机几位
        this.identifyCode +=
          this.identifyCodes[this.randomNum(0, this.identifyCodes.length)];
      }
    },
    //随机数字:用于当角标拿字符串的值
    randomNum(min, max) {
      return Math.floor(Math.random() * (max - min) + min);
    },
    submit() {
      console.log("验证码:", this.identifyCode);
      console.log("用户输入的验证码:",this.formLogin.code);
      console.log('是否验证通过:',this.identifyCode==this.formLogin.code);
    },
  },
};
</script>


2. 滑动验证

在这里插入图片描述

  • dentify.vue
<template>
<!-- 滑动验证码 -->
  <div ref="dragDiv" class="drag">
    <div class="drag_bg"></div>
    <div class="drag_text">{{ confirmWords }}</div>
    <div ref="moveDiv" :class="{'handler_ok_bg':confirmSuccess}" class="handler handler_bg"
         style="position: absolute;top: 0px;left: 0px;" @mousedown="mousedownFn($event)"></div>
  </div>
</template>

<script>
  export default {
    data () {
      return {
        beginClientX: 0, /* 距离屏幕左端距离 */
        mouseMoveStata: false, /* 触发拖动状态  判断 */
        maxwidth: '', /* 拖动最大宽度,依据滑块宽度算出来的 */
        confirmWords: '拖动滑块验证', /* 滑块文字 */
        confirmSuccess: false /* 验证成功判断 */
      }
    },
    mounted () {
      this.maxwidth = this.$refs.dragDiv.clientWidth - this.$refs.moveDiv.clientWidth;
      document.getElementsByTagName('html')[0].addEventListener('mousemove', this.mouseMoveFn);
      document.getElementsByTagName('html')[0].addEventListener('mouseup', this.moseUpFn)
    },
    methods: {
      mousedownFn: function (e) {
        if (!this.confirmSuccess) {
          e.preventDefault && e.preventDefault(); // 阻止文字选中等 浏览器默认事件
          this.mouseMoveStata = true;
          this.beginClientX = e.clientX;
        }
      },
      // mousedoen 事件
      successFunction () {
        this.confirmSuccess = true
        this.confirmWords = '验证通过';
        if (window.addEventListener) {
          document.getElementsByTagName('html')[0].removeEventListener('mousemove', this.mouseMoveFn);
          document.getElementsByTagName('html')[0].removeEventListener('mouseup', this.moseUpFn);
        } else {
          document.getElementsByTagName('html')[0].removeEventListener('mouseup', () => {});
        }
        document.getElementsByClassName('drag_text')[0].style.color = '#fff'
        document.getElementsByClassName('handler')[0].style.left = this.maxwidth + 'px';
        document.getElementsByClassName('drag_bg')[0].style.width = this.maxwidth + 'px';
      },
      // 验证成功函数
      mouseMoveFn (e) {
        if (this.mouseMoveStata) {
          let width = e.clientX - this.beginClientX;
          if (width > 0 && width <= this.maxwidth) {
            document.getElementsByClassName('handler')[0].style.left = width + 'px';
            document.getElementsByClassName('drag_bg')[0].style.width = width + 'px';
          } else if (width > this.maxwidth) {
            this.successFunction();
            console.log('验证成功');
          }
        }
      },
      // mousemove事件
      moseUpFn (e) {
        this.mouseMoveStata = false;
        var width = e.clientX - this.beginClientX;
        if (width < this.maxwidth) {
          document.getElementsByClassName('handler')[0].style.left = 0 + 'px';
          document.getElementsByClassName('drag_bg')[0].style.width = 0 + 'px';
        }
      }
    }
  }
</script>

<style scoped>
    .drag{
        position: relative;
        background-color: #e8e8e8;
        width: 100%;
        height: 34px;
        line-height: 34px;
        text-align: center;
    }
    .handler{
        width: 40px;
        height: 32px;
        border: 1px solid #ccc;
        cursor: move;
    }
    .handler_bg{
        background: #fff url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA3hpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNS1jMDIxIDc5LjE1NTc3MiwgMjAxNC8wMS8xMy0xOTo0NDowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDo0ZDhlNWY5My05NmI0LTRlNWQtOGFjYi03ZTY4OGYyMTU2ZTYiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NTEyNTVEMURGMkVFMTFFNEI5NDBCMjQ2M0ExMDQ1OUYiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NTEyNTVEMUNGMkVFMTFFNEI5NDBCMjQ2M0ExMDQ1OUYiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTQgKE1hY2ludG9zaCkiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo2MTc5NzNmZS02OTQxLTQyOTYtYTIwNi02NDI2YTNkOWU5YmUiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6NGQ4ZTVmOTMtOTZiNC00ZTVkLThhY2ItN2U2ODhmMjE1NmU2Ii8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+YiRG4AAAALFJREFUeNpi/P//PwMlgImBQkA9A+bOnfsIiBOxKcInh+yCaCDuByoswaIOpxwjciACFegBqZ1AvBSIS5OTk/8TkmNEjwWgQiUgtQuIjwAxUF3yX3xyGIEIFLwHpKyAWB+I1xGSwxULIGf9A7mQkBwTlhBXAFLHgPgqEAcTkmNCU6AL9d8WII4HOvk3ITkWJAXWUMlOoGQHmsE45ViQ2KuBuASoYC4Wf+OUYxz6mQkgwAAN9mIrUReCXgAAAABJRU5ErkJggg==") no-repeat center;
    }
    .handler_ok_bg{
        background: #fff url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA3hpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNS1jMDIxIDc5LjE1NTc3MiwgMjAxNC8wMS8xMy0xOTo0NDowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDo0ZDhlNWY5My05NmI0LTRlNWQtOGFjYi03ZTY4OGYyMTU2ZTYiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NDlBRDI3NjVGMkQ2MTFFNEI5NDBCMjQ2M0ExMDQ1OUYiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NDlBRDI3NjRGMkQ2MTFFNEI5NDBCMjQ2M0ExMDQ1OUYiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTQgKE1hY2ludG9zaCkiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDphNWEzMWNhMC1hYmViLTQxNWEtYTEwZS04Y2U5NzRlN2Q4YTEiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6NGQ4ZTVmOTMtOTZiNC00ZTVkLThhY2ItN2U2ODhmMjE1NmU2Ii8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+k+sHwwAAASZJREFUeNpi/P//PwMyKD8uZw+kUoDYEYgloMIvgHg/EM/ptHx0EFk9I8wAoEZ+IDUPiIMY8IN1QJwENOgj3ACo5gNAbMBAHLgAxA4gQ5igAnNJ0MwAVTsX7IKyY7L2UNuJAf+AmAmJ78AEDTBiwGYg5gbifCSxFCZoaBMCy4A4GOjnH0D6DpK4IxNSVIHAfSDOAeLraJrjgJp/AwPbHMhejiQnwYRmUzNQ4VQgDQqXK0ia/0I17wJiPmQNTNBEAgMlQIWiQA2vgWw7QppBekGxsAjIiEUSBNnsBDWEAY9mEFgMMgBk00E0iZtA7AHEctDQ58MRuA6wlLgGFMoMpIG1QFeGwAIxGZo8GUhIysmwQGSAZgwHaEZhICIzOaBkJkqyM0CAAQDGx279Jf50AAAAAABJRU5ErkJggg==") no-repeat center;
    }
    .drag_bg{
        background-color: #7ac23c;
        height: 34px;
        width: 0px;
    }
    .drag_text{
        position: absolute;
        top: 0px;
        width: 100%;text-align: center;
        -moz-user-select: none;
        -webkit-user-select: none;
        user-select: none;
        -o-user-select:none;
        -ms-user-select:none;
    }
</style>



  • index.vue
<template>
  <div class="home">
   <!--验证码组件-->
    <dentify></dentify>
  </div>
</template>

3. 拼图验证

在这里插入图片描述

  • 安装插件
npm install vue-puzzle-vcode --save
<template>
    <div>
        <Vcode :show="isShow" @success="success" @close="close" @fail='fail'></Vcode>
        <button @click="submit">登录</button>
    </div>
</template>

<script>
    import Vcode from "vue-puzzle-vcode";
    export default {
        components: {
            Vcode
        },
        data() {
            return {
                isShow: false, // 验证码模态框是否出现
            }
        },
        methods: {
            submit(){
                this.isShow = true;
            },
            // 用户通过了验证
            success(msg){
                this.isShow = false; // 通过验证后,需要手动隐藏模态框
                console.log('验证通过');
            },
            // 用户点击遮罩层,应该关闭模态框
            close(){
                this.isShow = false;
            },
            // 用户验证失败
            fail(){
                console.log('验证失败');
            }
        }
    }
</script>

<style scoped>

</style>


  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
好的,我会尽力回答您的问题。针对您的问题,可以使用以下步骤实现: 1.在Vue3项目中,安装 `vue-recaptcha` 包,这个包实现了谷歌验证码功能。 2.在 `index.html` 文件中,引入次包需要的JS文件,如下所示: ```html <script src="https://www.google.com/recaptcha/api.js?render=reCAPTCHA_site_key"></script> ``` 其中 `reCAPTCHA_site_key` 是您在谷歌开发者网站上申请的Site key。 3.在 `App.vue` 中,添加如下代码: ```html <template> <div> <div ref="captcha"></div> <button @click="verify">Verify</button> </div> </template> <script> import { ref } from 'vue'; import { createRecaptcha } from 'vue-recaptcha'; export default { setup() { const captchaRef = ref(null); let captchaToken = null; // 创建recaptcha实例,并记录token createRecaptcha({ siteKey: 'reCAPTCHA_site_key', size: 'normal', container: captchaRef.value, badge: 'inline', callback: function (token) { captchaToken = token; }, }); function verify() { // 发送captchaToken 到后端进行验证 console.log(captchaToken); } return { captchaRef, verify }; }, }; </script> ``` 在 `createRecaptcha` 方法中,我们可以设置一些参数来指定验证码组件的属性,如 `siteKey`、`size`、`container`、`badge` 以及 `callback` 等等。这里的 `callback` 方法会在用户成功进行验证后被调用,返回一个token参数,可以在后端使用来验证验证码是否正确。 4.在后端中,通过接收到的 `captchaToken` 参数,向谷歌服务器发送请求来验证用户的验证码是否正确。如果正确,后端可以返回一个成功的信息给前端,否则返回一个失败的信息。 以上就是使用 `vue-recaptcha` 包来实现验证码验证的方法。希望对您有所帮助!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

博客zhu虎康

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值