验证码WEB端产品调研(二):极限验证

本文是验证码系列的第二篇。笔者的写作顺序基于心中排名,所以这次为大家带来的是极限验证——GeeTest。

写到这里可能会有人质疑:难道阿里、腾讯、网易(以下简称ATN)的名气和实力不是比极验强吗?不可否认,但我们讨论的只是验证码:

  • 逻辑上,知名度高,综合实力强,不代表垂直领域实力也一定强——当然,并不否认ATN具备这样的人才和实力。这应该很好理解。玩吉他的人都知道YAMAHA,但YAMAHA的吉他却不见得是最好的——大师可能更喜欢Martin or Taylor,或者纯私人订制。换句话说:如果你有一把YAMAHA FG730,发朋友圈会有很多人点赞竖大拇指,但是也有人会给你一个手动微笑。

  • 市场上,极验在验证码领域已深耕多年,合作伙伴从直播、金融、电商,到资讯、游戏、航旅,甚至...政府,且号称有16w家企业正在使用。实力和人脉,可见一斑;而ATN的验证码服务只是其云平台下的一个分支,官网均未专门介绍具体合作方和数量。笔者虽没有详实的数据证明ATN接入方比极验少,但从个人上网经历来看,极验显然更“面熟”。起码都在用了。具体极验官网可查询,一张图感受下:

    验证码WEB端产品调研(二):极限验证_第1张图片

优势往往就是这样建立并扩大的:当你和一个行业的Top 3合作愉快的时候

遗憾的是,极验并没有给笔者任何软文费。鉴于此便不再继续吹了。下面还是从产品和技术层面聊一聊。

产品背景

极验目前的产品已经升级为3.0:


验证码WEB端产品调研(二):极限验证_第2张图片

其实这三代的产品,目前是共存的势态:

存在即合理

1.0

1.0代表的是键盘输入型字符验证码,开发成本低,常用开源框架即可搞定(如Kaptcha 、JCaptcha)。其设计思路就一点:
如何让生成的问题人可以解答,而机器不可以


因此传统验证码势必要在让机器感到压力山大的事情上做文章。但纯图片上做的文章,总是可以一物降一物:
左侧是验证码常用技术,右侧是对应的破解方法

当网站本身被频繁突破意义不大时,自然不用考虑这些对抗上的“短兵相接”。但就此类验证码而言,最明显的问题是:

  • 每次都要敲键盘输入
  • 为了防范图像识别破解,便增大识别难度,导致有时候人都难以识别

更有甚者直接利用“人类(大学生或许更准确)目前在认知学上对机器的优势“,在图片上直接祭出了高数,将反人类做到极致:

验证码WEB端产品调研(二):极限验证_第3张图片

当然,上图可能只是一个段子。总之极验官网已经号称对此没有兴趣:字符验证码不在服务范围。而这也是大势所趋: 验证码本身没有任何商业价值,为了阻挡机器会自带反人类属性。因此设计时一定要同时兼顾安全和用户体验。对于一些电商类的网站,用户体验甚至是摆在首位的。

2.0

2.0产品,极验称其为”行为式验证“。代表作是滑动拼图验证码。目前也是各大验证码平台的标配:

验证码WEB端产品调研(二):极限验证_第4张图片

为什么官网2.0的配图不是点选验证码?点选同样是标配,极验也有这款产品:
验证码WEB端产品调研(二):极限验证_第5张图片

笔者认为,主要原因是:
1)体验不如滑动——点击虽然比输入更便捷,但识别文字依然要花大量时间,尤其是当备选汉字远多于待验证汉字。
2)安全性不输于滑动(如果设计足够好),但其原理并非潮流所向——想要破解,首先要能抠出图片中的汉字,保证所有的汉字都被识别,且能够顺序和待验证汉字对上。这里穷举法(随便点三个)是没有用的,或者说成功概率很小(1/P(n,m))。因为只要错一个字就会刷新。可以看出,其校验原理更侧重前端展示,并不过分依赖行为分析。 既让用户可见,又要在可见基础上安全,就势必带来体验的下降,这还是和字符验证码有殊途同归的意思。
所以2.0强调行为,也是基于思路的转换: 弱化前端展示,强化后台分析,在不可见之处强化安全。
对滑动拼图而言,滑到正确位置只是一个必要条件,用户行为特征的提取才是核心。通过采集并分析用户使用鼠标拖动滑块的行为特征(速度、频率、耗时等)来判定是人还是机器。对用户来说,体验上比输入或点选字符要更轻松愉快,还兼具一定趣味性。但是便捷性往往和安全性相冲突:理论上只要机器模拟出人的行为,就可以绕过验证(有人可能会第一时间联想到按键精灵)。其实是否轻松,就看对行为判定是否精准了。这类判定,可以基于一些固定的规则(如滑动时间小于某个阈值),也可以引入机器学习分析特征量(如Kmeans做聚类分析),看各家的思路和实力了。未来这些偏后端的技术才是卖点,也不会轻易开源。因此此类验证码更多还是各类验证码平台提供,接入是有偿的。
知乎上有一位叫@darbra的兄弟,对破解极验2.0产品饶有兴趣。他总结出了 selenium大法 和 requests基本法,号称破率分别是98%和80%。 其Github上的代码7.4还有更新。有兴趣的读者可以尝试。

3.0

3.0时代则伴随着人工智能的浪潮全面进化,强调的则是进一步弱化前端+强化机器学习。前端越简单越好,一个按钮,一个滑块,一个复选框即可,甚至...nothing。个人认为,目前只有三家公司在这方面引领市场:Google,极验和阿里。

1)Google第一篇已经画了大量篇幅介绍,已经进化到“化无形为有形”的invisible reCAPTCHA,验证码实体完全透明,是目前来说产品理念上最领先的(技术上就不谈了)。
2)阿里和极验是第二档,区别在于一个是滑块,一个是按钮。相当于Google的noCAPTCHA产品。


验证码WEB端产品调研(二):极限验证_第6张图片

验证码WEB端产品调研(二):极限验证_第7张图片

极验的3.0产品思想,其实是官网提到的“验证码形如按钮,更像按钮一样百搭”——也就是说这个按钮会一直存在,只不过普通合法用户,需要多点一下它来进行人机识别罢了。只有非法用户时才会出现滑动拼图或图文点选验证。
如果极验有4.0,笔者大胆推测方向是invisible。
技术层面则强调使用了人工智能——其实各公司对应的2.0产品,应该都用到了。按照极验官方的说法:
恶意程序模仿人类行为轨迹对验证码进行破解针对模拟,极验拥有超过4000万人机行为样本的海量数据利用机器学习和神经网络构建线上线下的多重静态、动态防御模型识别模拟轨迹,界定人机边界
极验很可能是加强了人工智能的投入:例如新增更多特征量,优化识别算法等。毕竟机器学习还是一个数据为王的技术,没有足够多的训练样本是无法做到足够精准的。所以以极验目前的市场份额,是有这个实力优化的。但是加强了多少,效果如何,目前并没有太好的印证方式,毕竟今年4月才上线。看后期市场的反馈如何吧。

接入方式

同Google一样,极验的接入方式也如其UI一样:清爽简洁
按官网的说法:

  1. 引入初始化函数

  1. 调用初始化函数进行初始化
initGeetest({
    // 以下配置参数来自服务端 SDK
    gt: data.gt,
    challenge: data.challenge,
    offline: !data.success,
    new_captcha: data.new_captcha
}, function (captchaObj) {
    // 这里可以调用验证实例 captchaObj 的实例方法
})

结合配置参数:

验证码WEB端产品调研(二):极限验证_第8张图片

看似非常多,其实只有前面四个是必须,后面都是定制,按默认来均可不填。这样的参数配置,作为一家专业验证码公司,还是十分合理的—— 既要考虑到宕机问题,又得支持顾客的个性化需求。
参数含义,文档已经介绍的十分详细,Markdown排版阅读起来也很舒适,笔者便不再赘言。值得一提的是,第二个参数 challenge,在前面介绍的Google验证码参数也出现过,且含义基本一样。可能一半借鉴,一半致敬吧。

源码分析

细心的朋友会发现,步骤1中加载的是一个本地路径的gt.js,而非从极验服务器加载。按一般验证码公司的做法,给出一个http://static.geetest.com/static/tools/gt.js 就够了。极验则考虑到了failover层面——如果自己服务器故障怎么办?在目前机房容灾能力越来越强的今天,这么考虑仍然是一种非常专业和负责的做法。online offline皆可进行验证,这恰恰也是极验有别于其他验证码的特点之一。

下面还是回到gt.js——最近喜欢看源码。虽然笔者前端经验并不丰富,但是觉得有趣的东西,还是忍不住分享:

gt.js的主要功能是定义初始化验证码的函数initGeetest

最开始的地方如下:

"v0.4.6 Geetest Inc.";

(function (window) {
    "use strict";
    if (typeof window === 'undefined') {
        throw new Error('Geetest requires browser environment');
    }

……
})(window);

"v0.4.6 Geetest Inc."行首直接字符串秀出版本号和公司,一目了然。
这种重点要说的是"use strict"

严以律己,宽以待人

"use strict",严格模式,是Javascript非常好的一个特性,可能会大大节约你查错的时间。
先举个例子:

var zombie = {
    eyeLeft : 0,
    eyeRight: 1,
    // ... a lot of keys ...
    eyeLeft : 1
}
mingo= 5;
  1. eyeLeft出现了两次,你打算用哪个?
  2. mingo会是一个全局变量,如果被用于各种嵌套循环中会怎样?

这段代码严格模式下会抛出两个错误,而非严格模式不会报。
它以严格换来了如下好处,主要是以下两点:

  • 消除语法的一些不严谨之处,减少怪异行为
  • 消除代码运行的一些不安全之处
    最初网景在开发JavaScript可能存在一些考虑不周的情况,一些模棱两可的特性被人诟病,新手可能分不清是语法糖还是语法坑。
    user stick便是语言成熟化的一个方向。毕竟JavaScript将来会是一种全栈语言,尤其是在服务端Node.js逐渐强势的今天。

好像扯远了。其实笔者想说的是极验代码写的非常严谨。有一个细节:

var loadScript = function (url, cb) {
    var script = document.createElement("script");
    script.charset = "UTF-8";
    script.async = true;

    script.onerror = function () {
        cb(true);
    };
    var loaded = false;
    script.onload = script.onreadystatechange = function () {
        if (!loaded &&
            (!script.readyState ||
            "loaded" === script.readyState ||
            "complete" === script.readyState)) {

            loaded = true;
            setTimeout(function () {
                cb(false);
            }, 0);
        }
    };
    script.src = url;
    head.appendChild(script);
};

不知该写法应该是参考了JQuery如下源码:

callback = errorCallback = xhr.onload =
                                xhr.onerror = xhr.onabort = xhr.onreadystatechange = null

这么写主要还是因为:
IE的 script 元素支持onreadystatechange事件,不支持onload事件。FF则正好相反
如果要在一个

你可能感兴趣的:(验证码WEB端产品调研(二):极限验证)