使用Vue 实现滑动验证码功能


Posted in Javascript onJune 27, 2019

做网络爬虫的同学肯定见过各种各样的验证码,比较高级的有滑动、点选等样式,看起来好像挺复杂的,但实际上它们的核心原理还是还是很清晰的,本文章大致说明下这些验证码的原理以及带大家实现一个滑动验证码。

我之前做过 Web 相关开发,尝试对接过 Lavavel 的极验验证,当时还开发了一个 Lavavel 包: https://github.com/Germey/LaravelGeetest ,在开发包的过程中了解到了验证码的两步校验规则。

实际上这类验证码的校验是分为两个步骤的:

1.第一步就是前端的校验。一般来说,登录注册页面在点击提交的时候都会伴随着一个表单提交,在表单提交的时候会有 JavaScript 事件的触发。如果加入了验证码,那么在表单提交的时候会多加一个额外的验证,判断这个验证码是否已经成功完成了操作。如果没有的话,那就直接取消表单的提交,然后顺便提示说”您的验证没通过,请重新验证“,诸如此类的话。所以这一步就能防范”君子“只为了。

2.第二步就是服务端的校验。意思就是说表单提交之后,会有请求发送到服务器,这个请求中包含了很多数据,比如用户名、密码,如果对接了验证码的话,还会有额外的验证码的值,或者更复杂的加密后的 Token 值,服务器会对发过来的信息进行校验,如果验证通过,那么整个请求就成功了,返回正常的响应,否则返回错误的响应。所以如果想要通过程序来直接构造表单提交的时候,服务端就可以做进一步的校验,由于提交的验证码相关的信息都是和服务端的 Session 相关联的,另外再加上一些 CSRF 等的校验,所以这一步就能防范”小人“之为了。

上面就是验证码校验的两个阶段,一般来说为了安全性,在开发一个网站时需要客户端和服务端都加上校验,这样才能保证安全性。

本文章主要来介绍一下第一个阶段,也就是前端校验的验证码的实现,下面来介绍一下拖动验证码的具体实现。

需求

那么前端完成一个合格的验证码,究竟需要做成什么样子呢?

1.首先验证码有个大体的雏形,既然是拖动验证码,那就要拖动块和目标块,我们需要把拖动块拖动到目标块上就算校验成功。

2.验证码的一个功能就是来规避机器的自动操作,所以我们需要通过轨迹来判断这个拖动过程是真实的人还是机器,因此我们需要记录拖动的路径,路径经过计算之后可以发送到后端进行进一步的分类,比如对接深度学习模型来分类拖动轨迹是否是人。

以上就是验证码的两个基本要求,所以我们这里就来实现一下看看。

结果

这里就先给大家看看结果吧:

使用Vue 实现滑动验证码功能

可以看到图中有一个初始滑块,有一个目标滑块,如果把初始滑块拖动到目标滑块上才能校验成功,然后下方再打印拖动的轨迹,包含它的 x、y 坐标。

有了这些内容之后,就可以放到表单里面进行提交了,轨迹数据可以自行加密处理并校验来判断其是否合法。

具体实现

下面就具体讲解下这个是怎么实现的,实际上核心代码只有 200 行,下面对整个核心流程进行说明。

既然 Vue 这么火,那我这里就用 Vue 来实现啦,具体的环境配置这里就不再赘述了,需要安装的有:

Node.js: https://nodejs.org/en/
Vue-Cli: https://cli.vuejs.org/zh/

安装完成之后便可以使用 vue 命令了,新建个项目:

vue create drag-captcha

然后找一张不错的风景图,放到 public 目录下,后面我们会引用它。

另外这里需要一个核心的包叫做 vue-drag-drop,其 GitHub 地址为: https://github.com/cameronhimself/vue-drag-drop ,在目录下使用此命令安装:

npm install --save vue-drag-drop

安装好了之后我们就可以利用它来实现验证码了。

首先 vue-drag-drop 提供了两个组件,一个叫做 Drag,一个叫做 Drop。前者是被拖动对象,后者是放置目标,我们利用这两个组件构建两个滑块,将 Drag 滑块拖动到 Drop 滑块上就成功了。因此,我们要做的仅仅是把它们两个声明出来并添加几个检测方法就好了,至于拖动的功能,vue-drag-drop 这个组件已经给我们封装好了。

这里我们就直接在 App.vue 里面修改内容就好了,在 <template> 里面先声明一下两个组件:

<template>
 <div id="app">
  <div id="wrapper" :style="wrapperStyle">
   <drop class="drop" id="target"
      :class="{ 'over': state.over }"
      @dragover="onDragOver"
      @dragleave="onDragLeave"
      :style="targetStyle">
   </drop>
   <drag class="drag" id="source"
      :transfer-data="true"
      @dragstart="onDragStart"
      @dragend="onDragEnd"
      @drag="onDrag" v-if="!state.dragged"
      :style="sourceStyle">
    <div slot="image" id="float" :style="sourceStyle">
    </div>
   </drag>
  </div>
 </div>
</template>

很清晰了,一个 <drop> 和一个 <drag> 组件,里面绑定了一些属性,下面对这两个组件的常用属性作一下说明。

Drop

对于 Drop 组件来说,它是一个被放置的对象,被拖动滑块会放到这个 Drop 滑块上,这就代表拖动成功了。它有两个主要的事件需要监听,一个叫做 dragover,一个叫做 dragleave,分别用来监听 Drag 对象拖上和拖开的事件。

在这里,分别对两个事件设置了 onDragOver 和 onDragLeave 的回调函数,当 Drag 对象放到 Drop 对象上面的时候,就会触发 onDragOver 对象,当拖开的时候就会触发 onDragLeave 事件。

那这样的话我们只需要一个全局变量来记录是否已经将滑块拖动到目标位置即可,比如可以定一个全局变量 state,我们用 over 属性来代表是否拖动到目标位置。

因此 onDragOver 和 onDragLeave 事件可以这么实现:

onDragOver() {
  this.state.over = true
},
onDragLeave() {
  this.state.over = false
}

Drag

对于 Drag 组件来说,它是一个被拖动的对象,我们需要将这个 Drag 滑块拖动到 Drop 滑块上,就代表拖动成功了。它有三个主要的时间需要监听:dragstart、drag、dragend,分别代表拖动开始、拖动中、拖动结束三个事件,我们这里也分别设置了三个回调方法 onDragStart、onDrag、onDragEnd。

对于 onDragStart 方法来说,应该怎么实现呢?这里应该处理刚拖动的一瞬间的动作,由于我们需要记录拖动的轨迹,所以声明一个 trace 全局变量来保存轨迹信息,onDragStart 要做的就是初始化 trace 对象为空,另外记录一下初始的拖动位置,以便后续计算拖动路径,所以可以实现如下:

onDragStart(data, event) {
  this.init = {
    x: event.offsetX,
    y: event.offsetY,
  }
  this.trace = []
}

对于 onDrag 方法来说,就是处理拖动过程中的一系列拖动动作,这里其实就是计算当前拖动的偏移位置,然后把它保存到 trace 变量里面,所以可以实现如下:

onDrag(data, event) {
  let offsetX = event.offsetX - this.init.x
  let offsetY = event.offsetY - this.init.y
  this.trace.push({
    x: offsetX,
    y: offsetY,
  })
}

对于 onDragEnd 方法来说,其实就是检测最后的结果了,刚才我们用 state 变量里面的 over 属性来代表是否拖动到目标位置上,这里我们也定义了另外的 dragged 属性来代表是否已经拖动完成,dragging 属性来代表是否正在拖动,所以整个方法的逻辑上是检测 over 属性,然后对 dragging、dragged 属性做赋值,然后做一些相应的提示,实现如下:

onDragEnd() {
 if (this.state.over) {
  this.state.dragging = false
  this.state.dragged = true
  this.$message.success('拖动成功')
 }
 else {
  this.state.dragging = false
  this.state.dragged = false
  this.$message.error('拖动失败')
 }
 this.state.over = false
 }

OK 了,以上便是主要的逻辑实现,这样我们就可以完成拖动滑块的定义以及拖动的监听了。

接下来就是一些样式上的问题了,对于图片的呈现,这里直接使用 CSS 的 background-image 样式来设置的,如果想显示图片的某一个范围,那就用 background-position 来设置,这是几个核心的要点。

好,这里的样式设置其实也可以用 JavaScript 来实现,我们把它们定义为一些计算属性:

wrapperStyle() {
 return {
  width: this.size.width + 'px',
  height: this.size.height + 'px',
  backgroundImage: 'url(' + this.image + ')',
  backgroundSize: 'cover'
 }
},
targetStyle() {
 return {
  left: this.block.x + 'px',
  top: this.block.y + 'px'
 }
},
sourceStyle() {
 return {
  backgroundImage: 'url(' + this.image + ')',
  backgroundSize: this.size.width + 'px ' + this.size.height + 'px',
  backgroundPosition: -this.block.x + 'px ' + -this.block.y + 'px'
 }
}

另外这里还有一个值得注意的地方,就是 Drag 组件的 slot 部分:

<div slot="image" id="float" :style="sourceStyle"></div>

这部分定义了在拖动过程中随鼠标移动的图片样式,这里也和 Drag 滑块一样定义了一样的样式,这样在拖动的过程中,就会显示一个和 Drag 滑块一样的滑块随鼠标移动。

最后,就是拖拽完成之后,将滑动轨迹输出出来,这里我就直接呈现在页面上了, <template> 区域加入如下定义即可:

<div>
 <p v-if="state.dragged" id="trace">
  拖动轨迹:{{ trace }}
 </p>
</div>

好,以上就是一些核心代码的介绍,还有一些细节的问题可以完善下,比如滑块随机初始化位置,以及拖动样式设置。

最后再看一遍效果:

使用Vue 实现滑动验证码功能

可以看到我们首先拖动了 Drag 滑块,当 Drag 滑块拖动到 Drop 滑块上时,出现了白色描边,证明已经拖动到目标位置了。然后松手之后,触发 onDragEnd 方法,呈现拖动轨迹,整个验证码就验证成功了。

当然这只是前端部分,如果在这个基础上添加表单验证,然后再添加后端校验,并加上轨迹识别,那可谓是一个完整的验证码系统了,在这里就点到为止啦。

最后如果大家想也仿照实现一下的话,可以参考这个组件: https://github.com/cameronhimself/vue-drag-drop ,里面也介绍了其他的一些属性和事件,在某些情况下还是很有用的。

总结

以上所述是小编给大家介绍的使用Vue 实现滑动验证码,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

Javascript 相关文章推荐
JavaScript 权威指南(第四版) 读书笔记
Aug 11 Javascript
JavaScript中setUTCMilliseconds()方法的使用详解
Jun 12 Javascript
JavaScript html5 canvas画布中删除一个块区域的方法
Jan 26 Javascript
如何解决手机浏览器页面点击不跳转浏览器双击放大网页
Jul 01 Javascript
判断数组的最佳方法(推荐)
Oct 11 Javascript
百度地图去掉marker覆盖物或者去掉maker的label文字方法
Jan 26 Javascript
vue项目中axios使用详解
Feb 07 Javascript
Vue2.0 实现单选互斥的方法
Apr 13 Javascript
详解创建自定义的Angular Schematics
Jun 06 Javascript
layui获取选中行数据的实例讲解
Aug 19 Javascript
vue双向绑定及观察者模式详解
Mar 19 Javascript
详解uniapp的全局变量实现方式
Jan 11 Javascript
js变量值传到php过程详解 将php解析成数据
Jun 26 #Javascript
javascript触发模拟鼠标点击事件
Jun 26 #Javascript
JavaScript动态添加数据到表单并提交的几种方式
Jun 26 #Javascript
react koa rematch 如何打造一套服务端渲染架子
Jun 26 #Javascript
通过javascript实现段落的收缩与展开
Jun 26 #Javascript
vue.js 打包时出现空白页和路径错误问题及解决方法
Jun 26 #Javascript
Vue实现日历小插件
Jun 26 #Javascript
You might like
基于PHP CURL用法的深入分析
2013/06/09 PHP
CodeIgniter删除和设置Cookie的方法
2015/04/07 PHP
php把数组值转换成键的方法
2015/07/13 PHP
PHP错误处理函数
2016/04/03 PHP
php处理复杂xml数据示例
2016/07/11 PHP
prototype 的说明 js类
2006/09/07 Javascript
简单几行JS Code实现IE邮件转发新浪微博
2013/07/03 Javascript
JS和jquery获取各种屏幕的宽度和高度的代码
2013/08/02 Javascript
jQuery分别获取选中的复选框值的示例
2014/06/17 Javascript
jQuery动画特效实例教程
2014/08/29 Javascript
《JavaScript DOM 编程艺术》读书笔记之JavaScript 语法
2015/01/09 Javascript
推荐10 个很棒的 jQuery 特效代码
2015/10/04 Javascript
怎么限制input的text里输入的值只能是数字(正则、js)
2016/05/16 Javascript
浅析location.href跨窗口调用函数
2016/11/22 Javascript
JS 在数组指定位置插入/删除数据的方法
2017/01/12 Javascript
React Native如何消除启动时白屏的方法
2017/08/08 Javascript
JavaScript实现的数字与字符串转换功能示例
2017/08/23 Javascript
基于Vue框架vux组件库实现上拉刷新功能
2017/11/28 Javascript
nodeJS微信分享
2017/12/20 NodeJs
超好用的jQuery分页插件jpaginate用法示例【附源码下载】
2018/12/06 jQuery
js array数组对象操作方法汇总
2019/03/18 Javascript
通过循环优化 JavaScript 程序
2019/06/24 Javascript
JavaScript缓动动画函数的封装方法
2020/11/25 Javascript
[01:23]一分钟告诉你 DOTA2为什么叫信仰2
2014/06/20 DOTA
python的绘图工具matplotlib使用实例
2014/07/03 Python
Python实现遍历目录的方法【测试可用】
2017/03/22 Python
基于Pandas读取csv文件Error的总结
2018/06/15 Python
如何用python写一个简单的词法分析器
2018/12/18 Python
python 抓包保存为pcap文件并解析的实例
2019/07/23 Python
python dataframe NaN处理方式
2019/12/26 Python
Python3.9新特性详解
2020/10/10 Python
使用Python爬取小姐姐图片(beautifulsoup法)
2021/02/11 Python
ZWILLING双立人法国网上商店:德国刀具锅具厨具品牌
2019/08/28 全球购物
调查研究项目计划书
2014/04/29 职场文书
处级领导班子全部召开专题民主生活会情况汇报
2014/09/27 职场文书
腾讯云服务器部署前后分离项目之前端部署
2022/06/28 Servers