验证码(Captcha)的两种校对机制

1,030 阅读2分钟

前言

Captcha,中文全称为“全自动区分计算机和人类的图灵测试”,在实际使用中常常以验证码的形式出现在人们的视野中,即通过展示一张图片(或一段语音),要求用户输入其中的字符,以此来验证用户是否为人类。

验证码一般的校对流程为:验证码图片由后端生成,传输至前端,前端接受用户的输入,再发送给后端校对。但这其中就出现了问题,如何验证用户的输入是否正确?

两种验证机制

如何匹配用户输入和正确的验证码? 有两种方法:

  1. 将正确的验证码与会话绑定,这里姑且将这种验证码称为“状态验证码”。
  2. 将正确的验证码与键名绑定,这里姑且将这种验证码称为“无状态验证码”。

状态验证码

当访问某个网页的时候,服务器会在服务器端的内存里开辟一块内存,这块内存就叫做 sessionsession 与通过 cookie 与当前会话绑定。 状态验证码将正确的验证码存入 session 中,下面是一个简单的例子: 后端生成字符为abcd的验证码图片,并向 session 中存入键值对

"captcha"=>"abcd"

在接受用户输入后,服务端取出Session中的 capchaabcd,与用户输入进行比较,并返回比较结果。

无状态验证码

状态验证码将键值对存在 session 中,无状态验证码则将键值对存于缓存(Cache)中,但是缓存是所有会话共用的,所以需要生成唯一键名,并将键名与生成的图片一起提交至前端,前端返回用户输入的时候也应该同时返回这个键名。 下面是个简单例子:

后端生成字符为abcd的验证码图片,并生成键值对

$332hj5ghjk21h3jYU: "abcd"

同时将键名 $332hj5ghjk21h3jYU 与图片一起发送至前端。 前端接受用户输入后,返回后端的信息如下

{
	captcha: "用户的输入",
	key: "$332hj5ghjk21h3jYU"
}

服务端取出 key 后,再利用 key 从缓存中取出正确的验证码,与用户的输入进行比较,返回比较结果。 无状态验证码需要注意的一个点:在更新验证码时,用户可能会阻止 key 的更新,借此达成只输入一次验证码就可以重复提交表单,所以我们需要在后端每次验证完毕后,销毁缓存中对应的键值对