Skip to content

行为验证

前端实现

滑块图片验证

php
# 自定义参数
$params = [
    'src'           => '',  // 背景图片,尺寸 340 * 191
    'im_width'      => 340, // 画布宽度
    'im_height'     => 251, // 画布高度
    'im_type'       => 'png', // png 默认 jpg quality 质量
    'quality'       => 80,    // jpg quality 质量
    'bg_width'      => 340, // 背景宽度
    'bg_height'     => 191, // 背景高度
    'slider_width'  => 50,  // 滑块宽度
    'slider_height' => 50,  // 滑块高度
    'slider_border' => 2,   // 滑块边框
    'slider_bg'     => 1,   // 滑块背景数量
];

$type = 'slider';

/**
  * 获取验证参数
  * 内部使用了 laravel 的 cache 缓存,返回的是图片的 base64 、 缓存key 、滑块高度
  * @param string $type   验证码类型
  * @param array  $params 验证码自定义参数
  * @return arary
  */
$data = PosterManager::Captcha()->type($type)->config($params)->get();
$data = Captcha::type($type)->config($params)->get();

/** 
  * 验证
  * 前端根据相关滑块操作进行处理, 返回x坐标,返回 true 则验证成功
  * @param string     $key     缓存key
  * @param string|int $value   前端传回来的x坐标
  * @param int        $leeway  误差值
  * @return boolean
  */
$res = PosterManager::Captcha()->type($type)->check($key, $value, $leeway);
$res = Captcha::type($type)->check($key, $value, $leeway);

旋转图片验证

php
# 自定义参数
$params = [
        'src'           => '',  // 背景图片,尺寸 350 * 350 正方形都可 
        'im_width'      => 350, // 画布宽度
        'im_height'     => 350, // 画布高度
    	'im_type'       => 'png', // png 默认 jpg quality 质量
        'quality'       => 80,    // jpg quality 质量
    ];

$type = 'rotate';

/**
  * 获取验证参数
  * 内部使用了 laravel 的 cache 缓存,返回的是图片的 base64 、 缓存key
  * @param string $type   验证码类型
  * @param array  $params 验证码自定义参数
  * @return arary
  */
$data = PosterManager::Captcha()->type($type)->config($params)->get();
$data = Captcha::type($type)->config($params)->get();

/** 
  * 验证
  * 前端根据相关滑块操作进行处理, 返回x坐标,返回 true 则验证成功
  * @param string     $key     缓存key
  * @param string|int $value   前端传回来的旋转角度
  * @param int        $leeway  误差值
  * @return boolean
  */
$res = PosterManager::Captcha()->type($type)->check($key, $value, $leeway);
$res = Captcha::type($type)->check($key, $value, $leeway);

点击图片验证

php
# 自定义参数
$params = [
        'src'         => '',
        'im_type'     => 'png', // png 默认 jpg quality 质量
        'quality'     => 80,    // jpg quality 质量
        'font_family' => '', // 感谢站酷提供免费商用站酷库黑体、可自定义炫酷字体文件(绝对路径)
        'contents'    => '', // 自定义文字
        'font_count'  => 0,  // 文字长度
        'font_size'   => 42, // 字体大小
        'line_count'  => 0,  // 干扰线数量
        'char_count'  => 0,  // 干扰字符数量
    ];

$type = 'click';

/**
  * 获取验证参数
  * 内部使用了 laravel 的 cache 缓存,返回的是图片的 base64 、 缓存key
  * @param string $type   验证码类型
  * @param array  $params 验证码自定义参数
  * @return arary
  */
$data = PosterManager::Captcha()->type($type)->config($params)->get();
$data = Captcha::type($type)->config($params)->get();

/** 
  * 验证
  * 前端根据相关点击操作进行处理, 返回点击坐标数组,返回 true 则验证成功
  * @param string            $key     缓存key
  * @param string|int|array  $value   前端传回来的坐标数组
  * @return boolean
  */
$res = PosterManager::Captcha()->type($type)->check($key, $value);
$res = Captcha::type($type)->check($key, $value);

手动输入验证

php
# 自定义参数
$params = [
        'src'         => '',
        'im_width'    => 256,
        'im_height'   => 64,
        'im_type'     => 'png', // png 默认 jpg quality 质量
        'quality'     => 80,    // jpg quality 质量
        'type'        => 'number', // type = number 数字 alpha_num 字母和数字 math 计算 text 文字
        'font_family' => '', // 可自定义炫酷字体文件
        'font_size'   => 32, // 字体大小
        'font_count'  => 4,  // 字体长度
        'line_count'  => 5,  // 干扰线数量
        'char_count'  => 10,  // 干扰字符数量
    ];

$type = 'input';

/**
  * 获取验证参数
  * 内部使用了 laravel 的 cache 缓存,返回的是图片的 base64 、 缓存key
  * @param string $type   验证码类型
  * @param array  $params 验证码自定义参数
  * @return arary
  */
$data = PosterManager::Captcha()->type($type)->config($params)->get();
$data = Captcha::type($type)->config($params)->get();

/** 
  * 验证
  * 前端根据相关输入, 返回输入结果,返回 true 则验证成功
  * @param string            $key     缓存key
  * @param string|int|array  $value   输入结果
  * @return boolean
  */
$res = PosterManager::Captcha()->type($type)->check($key, $value);
$res = Captcha::type($type)->check($key, $value);

前端实现

参考仓库

gitee

captcha

vue-captcha

github

captcha

vue-captcha

js

直接引入js

html
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>图片验证DEMO</title>
    </head>
    <body>
        <button type="button" onclick="captcha()">
            验证
        </button>
    </body>
</html>
<script type="text/javascript" src="./slider/slider-min.js"></script>

滑块验证 js

javascript
<script type="text/javascript">
    // 开始验证
    function captcha(){
        // 根据 poster 获取验证参数
        Slider = new langSlider({
            title: '滑块安全验证', 
            start: function(Slider) {
                setTimeout(function(){
                    Slider.sliderStart({
                        sliderBg: './slider/img/slider.png', 
                        sliderKey: '1212', 
                        sliderY: 46
                    })
                }, 1000);
            },
            check: function(sliderKey, sliderX, Slider) {

                // 模拟调用验证接口
                const check = () => {
                    const leeway = 5 // 误差值
                    const value = 208 // 正确值
                    if(value >= (sliderX - leeway) && value <= (sliderX + leeway)){
                        // 成功调用该方法
                        Slider.sliderSuccess()
                    } else {
                        // 错误调用该方法
                        // 模拟调用获取验证参数接口
                        setTimeout(function(){
                            Slider.sliderError({
                                sliderBg: './slider/img/slider.png', 
                                sliderKey: '1212', 
                                sliderY: 46
                            })
                        }, 1000);
                    }
                }

                setTimeout(function(){
                    check()
                }, 1000)

            },
            refresh: function(Slider){
                
                setTimeout(function(){
                    Slider.sliderRefresh({
                        sliderBg: './slider/img/slider.png', 
                        sliderKey: '1212', 
                        sliderY: 46
                    })
                }, 1000);
            },
        })
    }
</script>

vue

安装

bash
npm install @kkokk/captcha
yarn add @kkokk/captcha

卸载

bash
npm uninstall @kkokk/captcha
yarn remove @kkokk/captcha

引入

js
// main.js 引入
import Captcha from '@kkokk/captcha'
Vue.use(Captcha)

调用

vue
<template>
  <div id="app">
    <button @click="open">验证</button>
    
    <slider-captcha 
      v-model="visible"
      :options="options"
      :loading="loading"
      @check="check"
      @close="close"
      @refresh="getSliderOptions"
      @error="getSliderOptions"
    >
    /** vue2 */
      <span slot="title">自定义标题-安全验证</span>
      <span slot="successText">自定义成功提示-登录中</span>
      <span slot="errorText">自定义错误提示-是不是太难了换一个</span>
      <span slot="tips">自定义提示拖动下方滑块完成拼图</span>
    /** vue2 */
    /** vue3 */
      <template #title>自定义标题-安全验证</template>
      <template #successText>自定义成功提示-登录中</template>
      <template #errorText>自定义错误提示-是不是太难了换一个</template>
      <template #tips>自定义提示拖动下方滑块完成拼图</template>
    /** vue3 */
    </slider-captcha>
  </div>
</template>

<script>

export default {
  name: 'App',
  data(){
    return {
      visible: false,
      loading: false,
      options: {}
    }
  },
  methods: {
    // 打开触发
    open() {
      this.visible = true
      this.getSliderOptions()
    },
    // 验证
    check(sliderKey, sliderX, done, error)
    {
      // 这里应该是验证是否成功的接口
      if(sliderX > 208 - 5 && sliderX < 208 + 5) {
        // 验证成功
        done()
      } else {
        // 验证错误
        error()
      }
    },
    // 关闭触发
    close() {

    },
    // 获取滑块验证参数
    getSliderOptions()
    {
      this.loading = true
      this.request({
        type: 'get',
        url: 'http://127.0.0.1:8111/',
        success: (res) => {
          this.options = {
            sliderImg: res.img,
            sliderKey: res.key,
            sliderY: res.y
          }
          this.loading = false
        }
      })
    },
    // 封装一个简单请求接口,方便测试
    request(obj) {
      return new Promise(function (resolve, reject) {
        var xhr = new XMLHttpRequest();

        switch(obj.type) {
          case 'get':
            xhr.open('GET', obj.url, true);
            xhr.onload = function() {
              resolve(obj.success(JSON.parse(this.responseText)))
            };
            xhr.onError= function () {
                    reject(obj.error({
                        status: this.status,
                        statusText: xhr.statusText
                    }));
                };
            break;
          case 'post':
            xhr.open('POST', obj.url, true);
            xhr.setRequestHeader('Content-Type', 'application/json');
            xhr.onreadystatechange = function() {
              if (this.readyState === XMLHttpRequest.DONE && this.status === 200) {
                resolve(obj.success(JSON.parse(this.responseText)))
              }
            };
            break;
        }
        
        xhr.send(JSON.stringify(obj.data));
      });
    }
  }
}
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

微不足道,绵薄之力