记一个node实现的图形验证码从0到1
记一个node实现的图形验证码从0到1
最近做了一个项目,需要用到给用户发送短信验证码,短信必然走的是第三方的服务。。 so 每一条都是收费的,所以在短信验证码之前,我们需要有一个图形验证码的验证来确定获取短信验证码的是一个人类 防止被人抓到接口无限刷-.-
整体流程的说明
由于机器环境的原因,没有选择
Redis
,图形验证码的结果保存方式为临时文件
- 生成验证码
- 验证有效性
- 验证成功&发送短信验证码
图形验证码的生成
图形验证码的生成,是在npm上找到了一个感觉还可以的包 https://www.npmjs.com/package/svg-captcha
该包生成的是SVG格式的验证码,较其他的那些验证码有一个优势,基本不需要安装其他的什么依赖(c++之类的)。
而且生成后的数据也不太容易会被破解,因为图片中的文字是通过路径渲染的方式来画到SVG里的,而不是直接简单的一个<text></text>
我们会在接口调用时,生成一张验证码图片,并且生成一个uuid
来确保唯一性。
将uuid
作为文件名来创建一个临时文件,并在文件中写入验证码对应的正确答案。
然后将验证码图片&uuid
发送到前端。
效果示意
希望GitHub能支持直接把SVG写到markdown里边去-.-
验证码有效性的验证
当前端获取到验证码,并且用户输入了对应的文本,我们需要做的就是验证是否正确。
验证接口会将UUID
和用户填写的验证码一并发过来。
- 检查文件是否有效
- 判断文件是否存在
- 判断文件是否过期(通过判断文件的
mtime
)
- 取出该文件对应的答案与用户输入的验证码进行对比
如果一致则将该文件的文本改为一个特定的字符串,以标识验证状态。 以上步骤中如果出现验证失败则直接将该验证码文件删除并返回结果。
验证完成后的使用
这时我们应该已经拿到了走完前边的两个接口,这时我们手中的
UUID
就相当于是发送短信验证码接口调用的一个钥匙,当然是一次性的。
我们就可以拿着这个UUID
去做我们想做的事儿,比如发送一个短信验证码-.-
将UUID
携带到请求的参数中,server就可以通过该UUID
来判断请求的有效性。
小结
该业务逻辑中所使用的一些node
依赖
-
fs
用来操作临时文件(创建删除查找) -
svg-captcha
用来生成验证码 -
node-uuid
用来生成不重复的唯一ID
后续的一些补充
因为每次创建一个验证码都会创建一个临时文件,虽说这个文件在验证过期后会进行删除,但是很难保证接口不会被恶意刷,导致服务器磁盘被临时文件撑满。
所以我们在这边使用了crontab
,定时每分钟清理一下五分钟前的文件来防止上述情况:
find XXX/tmp/ -mmin +5 -name "*.tmp" | xargs rm -rf
- 从javascript脚本混淆说起
- CoreOS etcd3 集群实践
- Spring MVC学习教程之流程表单提交,3步实现这个功能
- PXE 模式启动 CoreOS
- iPXE 模式启动 CoreOS(简单、推荐使用)
- CoreOS 已废弃组件
- Docker Compose version 3 使用详解
- Virtualbox 安装 Alpine Linux
- LinuxKit 使用
- Docker 实践遇到的问题(持续更新)
- GitHub Pages 常见问题
- SpyDealer深度剖析:一个广泛针对中国手机APP进行信息窃取的恶意软件
- Docker + Drone CI/CD 实践
- Petya及Notpetya的核心差异分析
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 原创分享 TiDB 的列式存储引擎是如何实现的?
- Qt音视频开发5-vlc事件订阅
- matlab中使用VMD(变分模态分解)
- TKE中挂载文件到CFS子目录
- Nginx Ingress on TKE 部署最佳实践
- 腾讯地图点聚合开发-实现地图找房功能
- 机器学习Tips:关于Scikit-Learn的 10 个小秘密
- R语言ggmap空间可视化机动车碰撞–街道地图热力图
- R语言ggmap空间可视化机动车交通事故地图
- 基于matlab的Lorenz系统仿真可视化
- 使用R语言对进行空间数据可视化
- R语言中基于混合数据抽样(MIDAS)回归的HAR-RV模型预测GDP增长
- R语言马尔可夫体制转换模型Markov regime switching
- Python中的ARIMA模型、SARIMA模型和SARIMAX模型对时间序列预测
- python3用ARIMA模型进行时间序列预测