前言
Captcha,中文全称为全自动区分计算机和人类的图灵测试,在实际使用中常常以验证码的形式出现在人们的视野中,即通过展示一张图片,要求用户输入图片中的字符,以此来验证用户是否为人类。
验证码一般的校对流程为:验证码图片由后端生成,传输至前端,前端接受用户的输入,再发送给后端校对。但这其中就出现了问题,如何匹配用户输入和正确的验证码?
两种验证机制
如何匹配用户输入和正确的验证码?
有两种方法:
- 将正确的验证码与会话绑定,这里姑且将这种验证码称为“状态验证码”。
- 将正确的验证码与键名绑定,这里姑且将这种验证码称为“无状态验证码”。
状态验证码
当访问某个网页的时候,服务器会在服务器端的内存里开辟一块内存,这块内存就叫做 session
,session
与通过 cookie
与当前会话绑定。
状态验证码将正确的验证码存入 session
中,下面是一个简单的例子:
后端生成字符为abcd的验证码图片,并向 session
中存入键值对
"captcha"=>"abcd"
在接受用户输入后,服务端取出Session中的 capcha
值 abcd
,与用户输入进行比较,并返回比较结果。
无状态验证码
状态验证码将键值对存在 session
中,无状态验证码则将键值对存于缓存(Cache)中,但是缓存是所有会话共用的,所以需要生成唯一键名,并将键名与生成的图片一起提交至前端,前端返回用户输入的时候也应该同时返回这个键名。
下面是个简单例子:
后端生成字符为abcd的验证码图片,并生成键值对
"$332hj5ghjk21h3jYU"=>"abcd"
同时将键名 $332hj5ghjk21h3jYU
与图片一起发送至前端。
前端接受用户输入后,返回后端的信息如下
{
captcha: "用户的输入",
key: "$332hj5ghjk21h3jYU"
}
服务端取出 key
后,再利用 key
从缓存中取出正确的验证码,与用户的输入进行比较,返回比较结果。
无状态验证码需要注意的一个点:在更新验证码时,用户可能会阻止 key 的更新,借此达成只输入一次验证码就可以重复提交表单,所以我们需要在后端每次验证完毕后,销毁缓存中对应的键值对。