使用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脚本实现Web页面信息交互
Oct 11 Javascript
定义select的边框颜色
Apr 28 Javascript
dtree 网页树状菜单及传递对象集合到js内,动态生成节点
Apr 14 Javascript
刷新页面的几种方法小结(JS,ASP.NET)
Jan 07 Javascript
jquery实现侧边弹出的垂直导航
Dec 09 Javascript
jQuery oLoader实现的加载图片和页面效果
Mar 14 Javascript
JavaScript获取网页表单提交方式的方法
Apr 02 Javascript
javascript数组去重的六种方法汇总
Aug 16 Javascript
JS模仿编辑器实时改变文本框宽度和高度大小的方法
Aug 17 Javascript
BootStrap 下拉菜单点击之后不会出现下拉菜单(下拉菜单不弹出)的解决方案
Dec 14 Javascript
node中的cookie的具体使用
Sep 13 Javascript
详解react组件通讯方式(多种)
May 06 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中的内存管理,PHP动态分配和释放内存
2013/06/28 PHP
PHP几个实用自定义函数小结
2016/01/25 PHP
PHP7匿名类用法分析
2016/09/26 PHP
PDO::prepare讲解
2019/01/29 PHP
javascript 按回车键相应按钮提交事件
2009/11/02 Javascript
UI Events 用户界面事件
2012/06/27 Javascript
JS去除右边逗号的简单方法
2013/07/03 Javascript
jquery插件之定时查询待处理任务数量
2014/05/01 Javascript
js实现网页随机切换背景图片的方法
2014/11/01 Javascript
JavaScript时间转换处理函数
2015/04/14 Javascript
最全的Javascript编码规范(推荐)
2016/06/22 Javascript
微信小程序 触控事件详细介绍
2016/10/17 Javascript
scroll事件实现监控滚动条并分页显示(zepto.js)
2016/12/18 Javascript
windows下更新npm和node的方法
2017/11/30 Javascript
JS中原始值和引用值的储存方式示例详解
2018/03/23 Javascript
Vue二次封装axios为插件使用详解
2018/05/21 Javascript
laydate只显示时分 不显示秒的功能实现方法
2019/09/28 Javascript
python字典多条件排序方法实例
2014/06/30 Python
数据挖掘之Apriori算法详解和Python实现代码分享
2014/11/07 Python
python使用Tesseract库识别验证
2018/03/21 Python
python3实现163邮箱SMTP发送邮件
2018/05/22 Python
判断python字典中key是否存在的两种方法
2018/08/10 Python
python opencv鼠标事件实现画框圈定目标获取坐标信息
2020/04/18 Python
Python函数的定义方式与函数参数问题实例分析
2019/12/26 Python
python函数定义和调用过程详解
2020/02/09 Python
python 删除excel表格重复行,数据预处理操作
2020/07/06 Python
UGG澳洲官网:UGG Australia
2018/04/26 全球购物
澳大利亚Mocha官方网站:包、钱包、珠宝和配饰
2019/07/18 全球购物
几道数据库的概念性面试题
2014/05/30 面试题
关于打架的检讨书
2014/01/17 职场文书
简历中的自我评价怎么写
2014/01/29 职场文书
税务干部鉴定材料
2014/02/11 职场文书
汽车机电维修工求职信
2014/09/30 职场文书
2014年党风建设工作总结
2014/11/19 职场文书
2015年教师新年寄语
2014/12/08 职场文书
MySQL定时备份数据库(全库备份)的实现
2021/09/25 MySQL