使用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 Array数组对象的扩展函数代码
May 22 Javascript
JS 两个字符串时间的天数差计算
Aug 25 Javascript
js禁止页面使用右键(简单示例代码)
Nov 13 Javascript
jquery实现简单的全选和反选功能
Jan 02 Javascript
实例详解JSON数据格式及json格式数据域字符串相互转换
Jan 07 Javascript
Jquery uploadify上传插件使用详解
Jan 13 Javascript
JavaScript实现的SHA-1加密算法完整实例
Feb 02 Javascript
Node.js编写爬虫的基本思路及抓取百度图片的实例分享
Mar 12 Javascript
JavaScript实现获取远程的html到当前页面中
Mar 26 Javascript
详解使用nvm管理多版本node的方法
Aug 30 Javascript
JS将时间秒转换成天小时分钟秒的字符串
Jul 10 Javascript
JavaScript进阶(二)词法作用域与作用域链实例分析
May 09 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编程注意事项的小结
2013/04/27 PHP
使用新的消息弹出框blackbirdjs
2008/10/16 Javascript
window.location和document.location的区别分析
2008/12/23 Javascript
来自国外的14个图片放大编辑的jQuery插件整理
2010/10/20 Javascript
jquery获得keycode的示例代码
2013/12/30 Javascript
jquery实现倒计时代码分享
2014/06/13 Javascript
对Web开发中前端框架与前端类库的一些思考
2015/03/27 Javascript
JS实现可直接显示网页代码运行效果的HTML代码预览功能实例
2015/08/06 Javascript
详解JavaScript函数对象
2015/11/15 Javascript
基于JS实现移动端访问PC端页面时跳转到对应的移动端网页
2020/12/24 Javascript
深入理解JS中的substr和substring
2016/04/26 Javascript
JS 学习总结之正则表达式的懒惰性和贪婪性
2017/07/03 Javascript
Angular弹出模态框的两种方式
2017/10/19 Javascript
使用node打造自己的命令行工具方法教程
2018/03/26 Javascript
如何实现一个简易版的vuex持久化工具
2019/09/11 Javascript
layui点击按钮页面会自动刷新的解决方案
2019/10/25 Javascript
一篇文章带你浅入webpack的DLL优化打包
2020/02/20 Javascript
[01:39](回顾)各路豪强针锋相对,几经鏖战四强产生
2014/07/01 DOTA
Python中__name__的使用实例
2015/04/14 Python
编写Python CGI脚本的教程
2015/06/29 Python
Python OpenCV中的resize()函数的使用
2019/06/20 Python
基于python进行抽样分布描述及实践详解
2019/09/02 Python
如何在Python 游戏中模拟引力
2020/03/27 Python
基于Python实现简单学生管理系统
2020/07/24 Python
python装饰器实现对异常代码出现进行自动监控的实现方法
2020/09/15 Python
CSS3属性box-shadow使用指南
2014/12/09 HTML / CSS
详解Html5 Canvas画线有毛边解决方法
2018/03/01 HTML / CSS
消防战士优秀事迹材料
2014/02/13 职场文书
入党积极分子学习优秀共产党员先进事迹思想汇报
2014/09/13 职场文书
县政府领导班子“四风”方面突出问题整改措施
2014/09/23 职场文书
普通党员自我剖析材料
2014/10/07 职场文书
高中生旷课检讨书
2014/10/08 职场文书
2014年生活老师工作总结
2014/12/23 职场文书
六一领导慰问欢迎词
2015/01/26 职场文书
个人原因辞职信模板
2015/05/13 职场文书
Spring Boot DevTools 全局配置学习指南
2022/03/31 Java/Android