前端人机交互极验功能详解

1,929 阅读4分钟

人机交互校验介绍

极验是一款人机交互页面效果系统,用户的行为没有满足要求,不给与下一步执行的机会

大致效果如下,用户如果没有把目标滑到指定区域就禁止下一步操作

这种小功能,在我们体验一个网站的时候是经常遇见的,在之前的传统网站中,用户输入用户名,密码,验证码就可以登录系统了,但是这样的网站不安全,有网络爬虫技术,可以通过“后端程序代码” 模拟账号登录,进而获得我们网站的信息

现在比较先进的网站,都使用“人机交互验证”功能,对登录者提出高要求,不让模拟登录得逞,相反只允许“实在的人”来登录系统并应用

这里我们主要使用的是极验的功能 极验官网:www.geetest.com/

这样做额好处就是防止账号暴力破解,不给模拟登录机会,增加系统的安全性

获取并导入js脚本

1. 获取好的gt.js文件放到  src/assets/js  目录下
    
2. 对不遵守eslint规范的代码稍加改动

由于我们之前使用的是ESLint语法的规范,对于我们引入的这个文件,在ESLint中要符合语法的要求,

eslint标准规范中有如下要求:

  1. 函数传递参数,不能直接传递boolean值,相反可以声明变量传递(gt.js文件中一共有4处,注意调整)
  2. 要通过 “===”恒等于 方式 判断两个字是否相等(上例为了使得数据类型是严格的字符串,额外调用了toString()方法,请注意)
  3. 不要设置空的回调函数实参,没有意义

开发步骤

人机交互验证开发流程:

开发人机验证步骤:

  1. axios向本身后端服务器发起请求,后端服务器会返回极验请求的秘钥信息
  2. 极验秘钥信息 + 用户行为 一并提交给 极验服务器 做判断,查验行为是否正确
methods: {
    login () {
      this.$refs.loginFormRef.validate(valid => {
        // 表单域校验成功
        if (valid) {
          // A. axios获得极验请求秘钥信息
          let pro = this.$http.get(`/captchas/${this.loginForm.mobile}`)
          pro
            .then(result => {
              // 服务器端返回极验的请求秘钥信息
              console.log(result) // config 【data】 request  headers status statusText
            })
            .catch(err => {
              return this.$message.error('获得极验初始校验信息错误:' + err)
            })

          // B. 账号真实校验,登录后台
          // this.loginAct()
        }
      })
    },
    // 校验账号真实性,登录后台
    loginAct () {
      // 账号真实性校验
      var pro = this.$http.post('/authorizations', this.loginForm)
      pro
        .then(result => {
          if (result.data.message === 'OK') {
            // 客户端记录用户的信息
            window.sessionStorage.setItem('userinfo', JSON.stringify(result.data.data))
            // 进入后台系统
            this.$router.push('/home')
          }
        })
        .catch(err => {
          return this.$message.error('用户名或密码错误' + err)
        })
    }
  }

创建窗口并应用

  1. 在login/index.vue中向引入gt.js文件
  2. 对返回的极验请求秘钥信息做接收处理(对象解构赋值)
  3. 调用initGeetest() 函数,生成极验窗口
    1. 添加product:'bind'
    2. verify()等方法调用
// 对gt.js文件进行导入
// gt.js文件本身没有做导出动作,所以就直接导入即可,此时系统增加一个全局变量,名称为 initGeeTest
import '@/assets/js/gt.js'
……
login () {
  this.$refs.loginFormRef.validate(valid => {
    // 表单域校验成功
    if (valid) {
      // A. axios获得极验初始校验信息
      let pro = this.$http.get(`/captchas/${this.loginForm.mobile}`)
      pro
        .then(result => {
          // 接收处理返回的极验请求秘钥信息
          let { data } = result.data
          // 显示极验应用窗口
          // 请检测data的数据结构, 保证data.gt, data.challenge, data.success有值
          window.initGeetest({
            // 以下配置参数来自服务端 SDK
            gt: data.gt,
            challenge: data.challenge,
            offline: !data.success,
            new_captcha: true,
            product: 'bind' // 没有按钮,通过登录按钮激活验证
          }, captchaObj => {
            // 这里可以调用验证实例 captchaObj 的实例方法
            captchaObj.onReady(() => {
              // 验证码ready之后才能调用verify方法显示验证码
              captchaObj.verify() // 显示验证码窗口
            }).onSuccess(() => {
              // your code
              // B. 校验账号真实性,登录
              this.loginAct()
            }).onError(() => {
              // your code
            })
          })
        })
        .catch(err => {
          return this.$message.error('获得极验初始校验信息错误:' + err)
        })
    }
  })
},
注意:在原来的配置参数中initGeetest()函数不加window的,但是由于是在Vue实例中使用,在这里未定义,所以不能使用,
我们观察gt.js文件可以知道,在gt.js文件中已经给他挂载成了全局变量,把他挂载到了window身上,如果我们想使用的话,需要使用window来调用这个函数

以上我们的基本功能已经基本实现,但是我们可以发现点击登录之后,窗口不能马上显示,在此期间设置按钮等待效果

极验窗口的显示需要消耗一定时间,为了增强用户体验,给“登录”按钮设置“等待”效果,同时考虑到严谨性,要同时设置disabled,使得按钮等待的同时也不让单击

<el-button :loading="ture/false" :disabled="true/false">登录</el-button>
步骤

1.data成员设置 isActive:false

isActive: false, // 按钮是否等待、禁用

2.给el-button登录按钮应用 loading 和 disabled属性,它们的值通过 btnLoading控制

<el-button 
           style="width:100%;" 
           :loading="isActive" 
           :disabled="isActive" 
           type="primary" 
           @click="login()">登录</el-button>

3.单击登录按钮后马上禁用 按钮 this.isActive= true

login () {
  this.$refs.loginFormRef.validate(valid => {
    // 表单域校验成功
    if (valid) {
      this.isActive = true // 登录按钮处于等待、禁用状态

4.极验交互窗口显示完毕 就恢复按钮 this.isActive= false

captchaObj.onReady(() => {
  ……
  this.isActive = false // 恢复按钮

当我们实现了按钮的切换之后,我们发现在用户重复点价之后,会创建多个DOM元素,这里我们对他进行一个优化处理,也就是使得用户多次点击登录按钮,关于验证窗口只生成一份

优化处理:

第一次生成人机窗口后,就给保存起来,后续再发生相同的动作直接使用即可

好处:用户等待时间缩短,页面上也不用生成许多div了

步骤

1.创建data成员 ctaObj

ctaObj: null, // 极验对象

2.第一次生成的人机窗口对象 赋予给 this.ctaObj= captchaObj

captchaObj.onReady(() => {
	……
  this.ctaObj = captchaObj // 已经极验对象赋予给ctaObj

3.用户重复单击登录窗口使用缓存好的极验对象

login () {
  this.$refs.loginFormRef.validate(valid => {
    // 表单域校验成功
    if (valid) {
      // 极验对象存在就直接调用
      if (this.ctaObj !== null) {
        return this.ctaObj.verify()
      }
      // 注意:按钮等待 要在 之后设置
      this.isActive = true // 登录按钮处于等待、禁用状态
注意:
    登录按钮等待的代码要在之后设置,这样的原因是使用之前的缓存极验对象,由于速度很快,按钮就不要做禁用状态了