首先,前端验证码和可靠二字完全不搭边我理解。但是后端验证码的话,后端首先需要进行一个 CPU 计算生成图片的过程,然后还需要维护一个对应状态,感觉成本有点高了,相比之下前端验证码对于后端来说就是无限轻量了。
有没有一种可能性是走两套方案,先前端再后端?比如注册验证这种场景,现在国内一般都是要调 API 发手机验证码的,为了保护 API 几乎都需要前置经过某种验证才能调用 API ,那么有没有可能,在前几次验证码时是前端验证,后端 API 根据用户 IP 或者什么其他信息维护一个屏蔽表,调用次数达到一定程度后再使用稍微安全一些的后端验证码这样?
这样前端的安全性要求其实也不高,能拦截 90%低端程序员就可以了。 有这样的项目吗?
1
yankebupt 2023-08-31 01:37:05 +08:00 2
你自己就可以做一个
首先图片是可以预生成的,你可以一次生成它 100W 张,扔服务器,扔CDN甚至让客户端预下载了都行 然后你根据系统时间给出一个分段随机序号 让客户端填完了把明文和序号发回来 根据系统时间规则是因为对方如果 replay attack 会在 5-10 分钟内失效 如果你想让客户端自己能判断对错,把明文的 Hash 也发过去让他自行验证。对面抓包看代码永远只知道 hash 不知道该填什么 必须看图 还不用维护状态 |
2
yankebupt 2023-08-31 01:39:23 +08:00
对了,扔 CDN 的话加个报复保护的 ip 限流……有很多人 cdn 被 D 的。
|
3
dusu 2023-08-31 01:44:58 +08:00 via iPhone
既然你觉得生成费劲成本高
给你个笨但是又高效的办法 为啥不提前生成一批验证码图片文件(总量为 36^长度) 不暴露路径的情况下 后端只需要生成 token 然后前端随机来用呢? 当然 还有很多可以优化的空间 例如 o 和 0 可以去掉等等举一反三… |
4
yankebupt 2023-08-31 01:52:36 +08:00
@dusu 这个方法和我刚才说的方法都有一个问题,就是 replay 攻击。
都是可以填一次验证码,然后 5-10 分钟内利用一个序号无限申请,因为没状态…… 我那个还应该加上一条,不仅应该根据系统时间,还应该根据请求 ip 分段,最大程度防止 replay 。 |
5
geelaw 2023-08-31 04:26:28 +08:00 via iPhone
@yankebupt #1 (经典计算机的)客户端不能自己验证,通常来说验证码的长度不足以阻挡离线枚举。
如果是注册验证,一个简单的避免重放的思路是让验证码和注册信息绑定。当然我没有仔细想过这样做的问题,标准解决方案才是正道。 |
6
0o0O0o0O0o 2023-08-31 08:08:31 +08:00 via iPhone 1
如果一定需要验证码,我建议且只建议 OP 购买并接入成熟服务,不要自研,你仅仅有图片验证码的概念就去自研的话约等于给攻击者送礼,包括 #1 - #4 。
|
7
zachlhb 2023-08-31 08:13:16 +08:00 via Android
可以用友验,极验这种服务的,前后端同时验证
|
8
yyf1234 2023-08-31 08:26:43 +08:00 via iPhone
极验不
|
9
yyf1234 2023-08-31 08:27:04 +08:00 via iPhone
就行了
|
10
ShuWei 2023-08-31 08:38:48 +08:00 1
考虑前端使用 wasm ,实时生成一个含语义理解的验证,比如实时生成并给出一个图片,让点击图片中特定内容的地方,然后验证坐标对不对。
服务端生成和验证,其实真没有多大的压力,你可能想得有点多了 或者,直接使用第三方的验证码服务,应该是最好的选择 |
11
wu67 2023-08-31 09:16:30 +08:00
我选择接入第三方的 sdk. 例如 阿里拉条公司 谷歌交通公司
|
12
lanxiner 2023-08-31 10:04:57 +08:00
近期正在研究验证码方案:
建议用第三方 阿里云、腾讯云都基本是按照使用量收费的, 非常便宜. , 但是不原生接入手机端, 其他的网易云盾、极验这些做的比较成熟各个端都可以接, 但是价格相对比较高. 用第三方的话基本上都有无痕验证, 他们有动态更新的风险识别算法,自动识别到有风险才会弹出验证码做进一步验证. (客户体验较高) |
13
mdn 2023-08-31 10:14:16 +08:00
不行,后端并不知道接口是否经过前端认证之后发送的
建议直接接入第三方验证,有无感验证,触发风控才需要弹窗验证 |
14
manasheep 2023-08-31 10:31:47 +08:00
“感觉成本有点高了”,毛毛雨了。
|
15
yankebupt 2023-08-31 11:03:00 +08:00
@geelaw 我不太懂离线枚举,但是不是可以把 Hash 设置复杂点(比如多 Hash 嵌套几十层),客户端用户点提交后基本1秒之后才验证这种……
反正服务端验证明文又不需要验证 Hash...... 但是离线反重放真的完全靠运气,对面上工具的话绝对没戏,所以只能防小白 |
16
yankebupt 2023-08-31 11:11:28 +08:00
@geelaw 要说非经典计算机,要有用的话肯定是把验证部分扔TEE里然后非对称加密握手拿到密钥,但又要买证书巨贵而且小程序之类还不能用……
|
17
Maerd 2023-08-31 11:15:54 +08:00
直接接入第三方验证吧,前端验证基本拦不住爬虫
|
18
yankebupt 2023-08-31 11:26:23 +08:00
@geelaw 我的意思是,服务端只需算出他生成的那些张的 Hash ,而客户端需要枚举所有。而且等客户端枚举完,服务端可能以及换了一批 Hash 组合了
或者如果不在意服务端亲自 Hash 一下的话,可以每次给客户端随机的Hash组合算法用于验证…… 比如 md5(sha1(salt(sha1(salt(md5()))))) salt(sha1(md5(sha1(salt(md5()))))) 还有真的很多人说成熟第三方,确实。为什么非得验证码。滑块不好么……第三方验证很贵么 |
19
dzdh 2023-08-31 11:35:37 +08:00
wasm + cookie 带个随机数 类似 totp 那样 10 秒误差时间范围内算个 6 位数数出来
|
20
hahaba 2023-08-31 11:43:10 +08:00
直接把接口加密了,前端的秘钥打散到各个文件再加密找都找不出来,连验证码都不用
|
21
yankebupt 2023-08-31 11:54:17 +08:00
比如那种定点滑块或者变异一点的二维滑块,客户端绘制,但是不是把验证结果发回去,而是把自己的绘制参数和用户的鼠标事件轨迹同时发回去服务器验证,用户就不知道验证逻辑是什么,而且为什么脚本自动滑有时候会失效。
|
22
geelaw 2023-08-31 11:55:27 +08:00
@yankebupt #16 经典计算机的对立面是量子计算机,这样说是因为利用量子计算可以让(发送给客户端的)程序只能(被客户端自行)运行一次,但经典计算机没有这种可能。
#18 >把明文的 Hash 也发过去让他自行验证。 我的解读是客户端会收到正确答案的 hash ,这样的话客户端可以自己尝试所有可能答案,计算它的 hash ,直到匹配为止,然后再把答案发给服务端。 >服务端只需算出他生成的那些张的 Hash ,而客户端需要枚举所有。而且等客户端枚举完,服务端可能以及换了一批 Hash 组合了 或者如果不在意服务端亲自 Hash 一下的话,可以每次给客户端随机的Hash组合算法用于验证…… 比如 md5(sha1(salt(sha1(salt(md5()))))) salt(sha1(md5(sha1(salt(md5()))))) 不太理解,客户端要想自己比对,当然需要知道如何计算 hash ,换用不同的算法没有意义。 In any case, 这个方案不好。此外,从攻防、补丁的角度思考效率也不高,应该从形式化和证明的角度思考。 |
23
libook 2023-08-31 11:56:26 +08:00 1
现在灰产,哪怕是低端程序员,Hack 接口是基操,前端验证码几乎没啥用,你只能防住完全不懂技术且也不会照着别人教程操作的人。从我们公司的经验来说,连小学生都知道怎么按照教程绕过限制薅羊毛。
除非你的产品需求非常明确就是防君子不防小人。 |
24
yankebupt 2023-08-31 11:57:40 +08:00
还有最新的Edge和Chrome免验证,由浏览器随时验证用户是否是真人,然后数字签名过去一个消息证明用户是真人,只要验证是Chrome的签名就行了。开源的Headless因为开源所以没证书也没签名,具体实现原理我也不清楚,可以参考下。
|
27
yankebupt 2023-08-31 12:38:59 +08:00
@geelaw 形式化验证虽然不万能,讲个笑话,验证码:1+1=2,黑客:等等,那只是个猜想,还没有证明!不能形式化验证!但其实该用一样用……
但形式化验证也并不是完全没用,但凡客户端有台 Loseless qubit 量子电脑,最次也是租了点超算时间,那什么 hash 或者 salt 都没有用。有没有一定要客户端可以知道对错的实现呢? 有! …… 只是估计是有的。 我们把判断对错的任务交给用户,不交给计算机了。 考虑两个滑块,每个 5-6 张验证码,其中有两个是一样的,两个滑块图片风格不一样,都做成渐变视频,让用户把两个数字拉一样了,点提交…… 判断只需两个滑块的位置阈值…… 这样本地计算机就不知道验证码对错了,只有用户知道…… 是不是形式化验证要的是这样的答案?我觉得是,但很可能用处不大…… |
28
yankebupt 2023-08-31 12:42:31 +08:00
附:知道对错是指用户能明确知道自己是否误输入,自愿承担多次误输入造成的封禁惩罚,知道看不清点刷新
如果明确的要拒掉错误输入的服务器请求,估计办不到的 |
29
mxT52CRuqR6o5 2023-08-31 12:43:44 +08:00 1
我建议直接把验证码去了,既不能阻挡机器人,又降低用户体验的东西为啥要做呢
|
30
yankebupt 2023-08-31 13:09:52 +08:00
@ mdn 被脚本或插件控制的时候不会发出签名信息
说的是因为浏览器验证用户是真人这段是闭源的。 主要因为大家有 Chromium 和 Webkit 是开源的的印象,这里是段闭源验证,套壳浏览器没有 当然可靠性没测过(没见人用过),所以不知道怎么样 |
31
zjsxwc 2023-08-31 13:11:22 +08:00
同意,后端验证码真没多少 cpu 成本,
比如 svg captcha , 后端每个验证码的字母都预先生成 svg 文本, 要用的时候也不过改变一下这个字母扭曲的参数, 后端验证码的成本和输出 html 没有区别。 https://github.com/NikolaiT/SVG-Captcha |
32
ganbuliao 2023-08-31 13:59:35 +08:00
用第三方的行为验证码
|
33
baobao1270 2023-08-31 15:45:03 +08:00
后端做风控+限频阿
|
34
LiuJiang 2023-08-31 17:06:33 +08:00
我也想问,有没有啥免费的验证服务,哈哈哈哈
|
35
loolac 2023-08-31 18:02:25 +08:00
手机扫码验证吧
|
36
vueli 2023-08-31 19:27:48 +08:00
后端可以返回验证码图片,几 KB
|
37
liuidetmks 2023-09-01 09:20:01 +08:00
能不能换个思路,使用,类似于比特币
你的请求的参数是 a ,找到随机 b 使得 sha256(a + b) 前面 20 个 bit 是 0 。(20 如果影响普通用户体验可以设置成 19 ,18) b 作为 参数的签名 一起发送给服务器,服务器简单验证就行了 这样批量刷就变得很困难了 如果想继续增加刷 api 成本,可以使用 scrypt 这类消耗内存形 HASH 替代 sha256 |