记一个node实现的图形验证码从0到1

Author Avatar
Blued 8月 17, 2017
  • 在其它设备中阅读本文章

最近做了一个项目,需要用到给用户发送短信验证码,短信必然走的是第三方的服务。。
so 每一条都是收费的,所以在短信验证码之前,我们需要有一个图形验证码的验证来确定获取短信验证码的是一个人类。
防止被人抓到接口无限刷-.-

整体流程的说明

由于机器环境的原因,没有选择Redis,图形验证码的结果保存方式为临时文件-.-

  1. 生成验证码
  2. 验证有效性
  3. 验证成功&发送短信验证码

图形验证码的生成

图形验证码的生成,是在npm上找到了一个感觉还可以的包 https://www.npmjs.com/package/svg-captcha

该包生成的是SVG格式的验证码,较其他的那些验证码有一个优势,基本不需要安装其他的什么依赖(c++之类的)。
而且生成后的数据也不太容易会被破解,因为图片中的文字是通过路径渲染的方式来画到SVG里的,而不是直接简单的一个<text></text>

我们会在接口调用时,生成一张验证码图片,并且生成一个uuid来确保唯一性。
uuid作为文件名来创建一个临时文件,并在文件中写入验证码对应的正确答案。
然后将验证码图片&uuid发送到前端。

效果示意

希望GitHub能支持直接把SVG写到markdown里边去-.-

验证码有效性的验证

当前端获取到验证码,并且用户输入了对应的文本,我们需要做的就是验证是否正确。

验证接口会将UUID和用户填写的验证码一并发过来。

  1. 检查文件是否有效
    1. 判断文件是否存在
    2. 判断文件是否过期(通过判断文件的mtime
  2. 取出该文件对应的答案与用户输入的验证码进行对比

如果一致则将该文件的文本改为一个特定的字符串,以标识验证状态。
以上步骤中如果出现验证失败则直接将该验证码文件删除并返回结果。

验证完成后的使用

这时我们应该已经拿到了走完前边的两个接口,这时我们手中的UUID就相当于是发送短信验证码接口调用的一个钥匙,当然是一次性的。

我们就可以拿着这个UUID去做我们想做的事儿,比如发送一个短信验证码-.-
UUID携带到请求的参数中,server就可以通过该UUID来判断请求的有效性。

小结

该业务逻辑中所使用的一些node依赖

  1. fs 用来操作临时文件(创建删除查找)
  2. svg-captcha 用来生成验证码
  3. node-uuid 用来生成不重复的唯一ID

后续的一些补充

因为每次创建一个验证码都会创建一个临时文件,虽说这个文件在验证过期后会进行删除,但是很难保证接口不会被恶意刷,导致服务器磁盘被临时文件撑满。

所以我们在这边使用了crontab,定时每分钟清理一下五分钟前的文件来防止上述情况:

find XXX/tmp/ -mmin +5 -name "*.tmp" | xargs rm -rf