验证安全2.0时代:浅谈验证码先锋——极验

152 阅读7分钟

背景

每到节假日,抢火车票这件事就像是一场没有硝烟的战争,几乎每个人都亲身体会过。在这个特殊的时刻,网络上总是充斥着“抢票”这个话题,大家纷纷在微信群、朋友圈里分享自己的购票经验和心酸故事。

随着越来越多的人投入到这场抢票大战中,黄牛们却像幽灵般在其中游刃有余。黄牛们通过非正常手段高价转售票务(如门票、火车票、演出票等)在短时间内获取大量票务,从中牟利。这种行为在各类热门活动(如演唱会、体育赛事、火车出行等)中非常普遍,影响了正常用户的购票体验。

为了打击这一现象,一些购票平台开始引入人机验证技术,试图通过分析用户行为、使用动态验证码等方式来判断请求是否来自真实用户。

今天我们就一起聊一聊一种主流的人机验证技术——极验。


目录

  1. 主要特征
  2. 实现原理
  3. 安全性
  4. 典型案例
  5. 应对策略
  6. 实例

主要特征

极验(Geetest)是一种被广泛应用于网络安全验证的技术,主要用于防止机器人和恶意攻击,提高应用程序的安全性。它通常通过挑战用户完成某个动作(如拖动、点击、识别图形等)来判断用户是否为真人。

  1. 多样化的验证方式:极验提供不同类型的验证码挑战,如滑动验证、点击验证和图形验证码等。根据不同场景选择合适的验证方式。

  2. 智能识别:采用机器学习和大数据分析,极验能够不断适应和识别用户行为,以提高验证的准确性和用户体验。

  3. 友好的用户体验:用户界面通常设计得简单直观,力求减少用户在验证过程中的困扰。

  4. 安全性高:通过使用多种技术手段,极验能够有效防止恶意攻击、刷票、机器人注册等行为。

  5. 可配置性:开发者可以根据业务需求配置验证的方式、触发条件和验证结果的处理逻辑。

实现原理

极验结合了机器学习、图形处理和人机交互等多种技术,以防止机器人和恶意攻击。以下是极验的核心实现原理和工作流程:

image.png

image.png

安全性

极验(Geetest)作为一款人机验证技术,在购票、注册和登录等场景中广泛应用,其主要目的是确保系统的安全性,并为真实用户提供良好的体验。以下是极验技术在安全性方面的一些关键特点:

image.png

典型案例

12360系统

相信大家都使用过12360软件购买火车票,便捷的购票方式本应让出行变得简单。然而,繁琐的验证流程却使得不少用户在实际操作中感到困惑和沮丧,从而影响了整体的使用体验。

主要还是用户体验问题,验证步骤繁琐,且验证码设计往往过于复杂,有的甚至需要用户辨认模糊的字母、数字、拼图或智商考试题,故意“刁难”用户。

复杂的验证设计对于部分用户来说,显得尤为挑战,技术不熟悉使用户容易受挫,购票过程中频繁遭遇验证失败或操作不顺时,这种负面体验不仅降低了他们对12360软件的满意度,导致信任感的下降。

虽然验证码和人机验证是为了保护购票者的合法权益,但过于复杂的验证过程却让用户体验受到了很大影响。希望未来的软件在安全性与用户体验之间能找到一个更好的平衡,让每个人都能顺利、愉快地购票。

谷歌人机验证

Google 验证是否为人机的机制主要依赖于 CAPTCHA(完全自动化公共图灵测试以告诉计算机和人类的差别)技术,尤其是在其 reCAPTCHA 系统中。其实现原理如下:

1. 数据收集与机器学习

Google 收集大量的用户交互数据,包括用户在完成 CAPTCHA 时的行为模式,例如鼠标移动轨迹、点击速度和输入方式。

通过分析这些数据,Google 使用机器学习算法训练模型,以识别人类与机器之间的行为差异。

2. 行为分析

reCAPTCHA 在用户访问网页时,会监测用户的行为。例如,当用户点击验证框时,系统会分析点击的方式、持续时间等信息。

对于正常的用户行为,系统会生成特定的模式,而机器人通常会表现出更固定和不自然的行为。

3. 任务难度调整

系统会根据用户的历史交互记录和当前行为动态调整 CAPTCHA 的难度。

例如,对于高风险用户,系统可能会要求完成更复杂的任务,如识别图片中的特定物体(“选择所有包含交通信号灯的图片”)等。

4. 重复学习

系统会不断更新和优化其算法,通过持续的用户数据反馈来改进模型,提高识别的准确性。

5. 无缝验证

在某些情况下,reCAPTCHA 会实现“无缝验证”,即用户在未被要求进行额外的验证步骤时,系统会自动判定用户为人类。

这种方式大大提升了用户体验,使得用户在完成验证时不会受到过多干扰。

通过以上机制,Google 能够有效区分人类用户与自动化的机器人,提高网站的安全性,同时保持较好的用户体验。

以上两款安全验证码的策略,各有千秋,前者通过设计复杂的验证方式能很大程度上打击黄牛,但却影响用户体验,增加用户挫败感;后者利用大数据更加智能地检测人类行为,却更适合应对简单场景,但更人性化智能化。

在安全性与用户体验之间需要找到一个平衡点

应对策略

极验(Geetest)作为一种人机验证/验证码解决方案,它采用了一系列灵活的应对策略来防止机器人的自动化攻击和恶意滥用。主要应对策略如下:

image.png

实例

下面是一个完整的使用 Geetest 验证的 Node.js 示例,包括前端和后端的实现。这将涉及到以下几个步骤:

  1. 在 Geetest 上注册,获取 IDKey
  2. 设置 Node.js 服务器,使用 Express 框架。
  3. 实现 Geetest 验证,在服务器端和客户端。

1. 安装依赖

首先,创建一个新的 Node.js 项目并安装需要的依赖。

mkdir geetest-example
cd geetest-example
npm init -y
npm install express body-parser axios dotenv

2. 创建 Node.js 服务器

创建一个名为 server.js 的文件,并添加以下代码:

// server.js
const express = require('express');
const bodyParser = require('body-parser');
const axios = require('axios');
require('dotenv').config();

const app = express();
const port = 3000;

// Middleware
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(express.static('public')); // 用于提供静态文件

// Geetest 配置
const geetestId = process.env.GEETEST_ID;
const geetestKey = process.env.GEETEST_KEY;

// 创建验证接口
app.get('/api/startCaptcha', (req, res) => {
    axios.post(`https://api.geetest.com/register.php`, {
        gt: geetestId,
    })
    .then(response => {
        console.log('结果response: ', response);
        res.json(response.data);
    })
    .catch(error => {
        console.error(error);
        res.status(500).send("创建异常");
    });
});

// 提交验证结果
app.post('/api/validateCaptcha', (req, res) => {
    const { geetest_challenge, geetest_validate, geetest_seccode } = req.body;

    const params = {
        id: geetestId,
        challenge: geetest_challenge,
        validate: geetest_validate,
        seccode: geetest_seccode,
    };

    axios.post(`https://api.geetest.com/validate.php`, params)
    .then(response => {
        if (response.data && response.data.success) {
            // 验证成功,可以定义对应的code编码
            res.send({ success: true, code: 200 });
        } else {
            // 验证失败,这里定义失败的code编码为426
            res.send({ success: false, code: 426 });
        }
    })
    .catch(error => {
        console.error(error);
        res.status(500).send("验证异常");
    });
});

// 启动服务器
app.listen(port, () => {
    console.log(`Server is running on http://localhost:${port}`);
});

创建一个 .env 文件,存放 Geetest 的 IDKey

GEETEST_ID=你的极验ID
GEETEST_KEY=你的极验KEY

在控制台中运行以下命令启动服务器:

node server.js

3. 创建前端页面

在项目目录中创建一个名为 public 的文件夹,并在其中创建一个 index.html 文件:

<!-- public/index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Geetest Example</title>
    <script src="https://static.geetest.com/static/js/geetest.js"></script>
</head>
<body>
    <h1>Geetest Example</h1>
    <button id="startCaptcha">Start Captcha</button>
    <div id="captchaContainer" style="display: none;"></div>

    <script>
        document.getElementById('startCaptcha').addEventListener('click', function() {
            fetch('/api/startCaptcha')
                .then(response => response.json())
                .then(data => {
                
                    console.log('data', data);
                    
                    if (data && data.success) {
                        const gt = new Geetest({
                            gt: data.gt,
                            challenge: data.challenge,
                            success: function() {
                                // 成功回调
                                document.getElementById('captchaContainer').style.display = 'block';
                            }
                        });
                        gt.on('success', function(data) {
                            // 发送给服务端
                            const { geetest_challenge, geetest_validate, geetest_seccode } = data;
                            fetch('/api/validateCaptcha', {
                                method: 'POST',
                                headers: {
                                    'Content-Type': 'application/json',
                                },
                                body: JSON.stringify({ geetest_challenge, geetest_validate, geetest_seccode }),
                            })
                            .then(response => response.json())
                            .then(result => {
                                if (result.success) {
                                    alert('验证成功');
                                } else {
                                    alert('验证失败');
                                }
                            });
                        });
                        gt.init();
                    }
                });
        });
    </script>
</body>
</html>

在浏览器中访问 http://localhost:3000,你应该能看到一个按钮,点击它可以启动极验验证码,完成验证后,结果将显示在弹窗中。