Skip to content

点选文字验证码

我们准备了 ba\ClickCaptcha 类,和 clickCaptcha 组件,实现了前端的点选文字验证码和服务端的二次验证。

使用思路

ts
clickCaptcha(id: string, callback?: (captchaInfo: string) => void, options: ClickCaptchaOptions = {})
  1. 用户提交表单等操作前,传递 验证码ID 调起文字点选验证码,用户完成验证后将生成 点选文字坐标信息(captchaInfo)
  2. 在验证完成回调中,将 验证码ID点选文字坐标信息 随表单数据发送到服务端,并在接口中使用对应方法对坐标信息进行二次验证
  3. 开发者往往无需关注 坐标信息,以及封装好的验证逻辑等,只需看懂下方示例即可方便快捷的使用 文字点选验证码

前端

ts
import { reactive } from 'vue'
import { uuid } from '/@/utils/random'
import clickCaptcha from '/@/components/clickCaptcha'

// 表单数据
const form = reactive({
    // 验证码ID,开发者自定义,随表单数据发送到服务端供二次验证
    captchaId: uuid(),
    // 用户点选的文字坐标信息,随表单数据发送到服务端供二次验证
    captchaInfo: '',
    // 假设的表单字段
    username: '',
    password: '',
})

const onSubmitPre = () => {
    // 假设表单设置了验证规则
    formRef.value?.validate((valid) => {
        if (!valid) return

        /**
         * 调用此函数,自动调起点选文字验证码弹窗
         * 参数一:验证码ID
         * 参数二:验证成功后的回调函数
         * 参数三:额外的可配置项
         */
        clickCaptcha(form.captchaId, (captchaInfo: string) => onSubmit(captchaInfo))
    })
}

const onSubmit = (captchaInfo = '') => {
    // 在回调函数中一定要更新 form 中的验证数据,否则服务端验证将失败
    form.captchaInfo = captchaInfo

    login('post', form).then((res) => {
        // 请求成功
    })
}

服务端

php
$captchaId   = $this->request->post('captchaId');
$captchaInfo = $this->request->post('captchaInfo');

$captcha = new \ba\ClickCaptcha();
if (!$captcha->check($captchaId, $captchaInfo)) {
    $this->error('验证码错误!');
}

// 您的业务逻辑...

点选验证码的实现思路

如果您需要在比如 uniapp 等其他平台实现点选验证码,实现思路如下,它非常简单!

  1. 携带一个自定义的 id 字符串请求验证码接口
  2. 该接口返回 一张base64编码的图片图片的宽高(通常为350*200)四个随机字符
  3. 您只需要渲染返回的图片,并要求用户按 四个随机字符 的顺序点击四下
  4. 将用户四次点击事件的坐标按简单规则拼接,同 id 发送至服务器即可完成验证
  5. 以上仅为思路,实现请直接参考 /web/src/components/clickCaptcha/index.vue

普通验证码

我们准备了 ba\Captcha 类,该类基于 TP 的验证码类改造而成:通过 Mysql 保存验证码而不是 Session 以更好的支持 API 访问。

使用验证码类的方法如下:

  1. 前端生成一个唯一的 id
  2. 携带 id 请求验证码生成接口,该接口应直接输出图片,比如:/index.php/api/common/captcha
  3. 提交表单时,携带 id,以对验证码的正确性进行验证。

验证码生成示例

php
// 接受ID
$captchaId = $this->request->request('id');

// 一些验证码的基本配置
$config    = array(
    'codeSet'  => '123456789',            // 验证码字符集合
    'fontSize' => 22,                     // 验证码字体大小(px)
    'useCurve' => false,                  // 是否画混淆曲线
    'useNoise' => true,                   // 是否添加杂点
    'length'   => 4,                      // 验证码位数
    'bg'       => array(255, 255, 255),   // 背景颜色
);

// 实例化验证码类,传递`ID`并输出验证码
$captcha = new Captcha($config);
return $captcha->entry($captchaId);

验证码验证示例

php
// 接受验证码和验证码ID
$data['captcha']   = $this->request->post('captcha');
$data['captchaId'] = $this->request->post('captcha_id');

$captchaObj = new Captcha();
if (!$captchaObj->check($data['captcha'], $data['captchaId'])) {
    $this->error('验证码错误!');
}

普通验证码高级应用

验证码类,不仅仅可以生成图像验证码,几乎支持所有:给用户展示/发送一个字符串,要求用户输入看到的字符进行身份验证的场景

发送邮箱验证码

php
// 准备一个 id ,此处使用一个前缀+发信邮箱地址,但总的来说它是完全自定义的
$id = 'user_email_verify:' . $this->auth->email;

$captcha = new Captcha();
$code    = $captcha->create($id);

// 将 $code 发送到用户邮箱,它是自动生成的字符串,您也可以通过参数二指定一个字符串
// ...
// $mail->send();

验证邮箱验证码

php
$id = 'user_email_verify:' . $this->auth->email;
$code = $this->request->post('code');
$captcha = new Captcha();
$captcha->check($code, $id);

给验证码设定一个 id,通过这个 id 生成的验证码自然可以通过该 id 完成验证,而 id 是完全自定义的。

普通验证码配置

验证码类带有默认的配置参数,也支持自定义配置,这些配置项包括:

配置项注释默认值
codeSet验证码字符串集合数字、大小写字母,(以去除1l0o等容易混淆的字符)
expire验证码过期时间(秒)600秒(10分钟)
useZh使用中文验证码false
zhSet中文验证码字符串一些预设的汉字
useImgBg使用图片背景false
fontSize验证码字体大小(px)25(px)
useCurve是否画混淆曲线true
useNoise是否添加杂点true
imageH验证码图片高度0:自动计算
imageW验证码图片宽度0:自动计算
length验证码位数验证码位数
fontttf验证码字体,不设置则随机获取
bg验证码背景色rgb[243, 251, 254]
reset验证成功后重置true