一个接口,浏览器每请求 100 次,弹出一次验证码,要求服务器端不记录浏览器对应 ip 的请求次数,该怎么实现?

2019-12-27 09:11:19 +08:00
 kisshere

如果通过服务器端记录客户端对应 ip 的请求次数,数据库会撑爆的,如何从验证客户端浏览器提供的数据下手,让这个接口,浏览器每请求 100 次,就弹出一次验证码?

$_COOKIE['requestCount']=$_COOKIE['requestCount']+1;
if($_COOKIE['requestCount']>100){show_captcha();}//这种逻辑就算了哈,小学生都能修改 cookie 破解
9012 次点击
所在节点    程序员
89 条回复
catror
2019-12-27 10:42:24 +08:00
IP 请求次数放内存里就完事了,如果要多台服务器全局限制的话就用 redis。
wml
2019-12-27 10:48:48 +08:00
@alphatoad 这样可能会导致用户体验不好 且想攻击重新请求一下就好了
jiaming1992
2019-12-27 11:06:06 +08:00
可以给用户发个通知,让用户记录,每请求一次在本本上画一笔,等到 100 个时让用户通知你。
zlhsvc
2019-12-27 11:07:49 +08:00
内存里就完事了,然后加个过期清理,你不可能永久记录这个次数吧
forgottencoast
2019-12-27 11:11:15 +08:00
@kisshere #3 说的就可以啊,客户端 Cookie 加密,如果没有携带参数就出验证码,这样清理 Cookie 这招就没用了。
Cookie 带 IP 地址,一换 IP 地址就弹验证码。
kisshere
2019-12-27 11:15:43 +08:00
@forgottencoast 比如用户请求了 3 次,3 经过加密成为一个字符串 asdf,用户 F12 抓到这个 asdf 后,每次都携带这个字符串 asdf 给提交给服务器,服务器每次解密后得出是 3,然后放行通过。。。。。。
snoopyxdy1
2019-12-27 11:21:24 +08:00
用 cookie 签名做就可以拉,第一次的话就无脑弹验证码
noahsophie
2019-12-27 11:30:44 +08:00
浏览器每请求 100 次,弹出一次验证码。这个就是防范普通用户的,所以前端怎么方便怎么来,其次服务端可以在网关层做处理,比如在 nginx 限制 IP 访问频率
darknoll
2019-12-27 11:33:03 +08:00
nginx 不行么
lihongjie0209
2019-12-27 11:33:20 +08:00
Ip + counter 放内存不就行了?
数据库会爆炸??? 全球的 IP 都会访问你们的接口?
passerbytiny
2019-12-27 11:38:25 +08:00
首先,客户端 IP 不是浏览器能决定的,那是中间网络决定的,你后面提到用代理池怕接口,那应该是想到这一点了。

然后,每请求 100 次弹出一次验证码这个逻辑不对,应该是:若短时间内连续请求 N 次,则接下来一段时间内必弹验证码,然后重置。一个 IP 的请求次数,并不是静态永久数据,而是动态瞬时数据,它的记录在首次请求的时候创建,在重置,或者超过监控时间的时候删除。(如果有心思,还可以考虑更花哨的重置和监控时机。)

最后,记录客户端对应 ip 的请求次数,一个 IP 就一条记录,如果要达到数据库爆仓的效果,那得短时间内几千万个新 IP 访问服务器,这时候你首要考虑的就不是爆仓,而是 DDOS 了。

所以,安心的记录吧,当然还是建议 Redis 记录,除了性能考虑外,你还可以不用做重置处理(由 redis 超时机制自动重置)
Sunyanzi
2019-12-27 12:04:48 +08:00
这需求能做 ... 不需要记录用户 IP ... 需要用户传四个元素 ... counter / nonce / timestamp / signature ...

如果不严谨要求不能挨重放的话 nonce 也可以去掉 ... 这样服务端就不存任何东西了 ...

不知道这种方式你能不能理解 ... 如果需要我可以写 DEMO ...
zgq3337
2019-12-27 12:07:16 +08:00
用服务器累加器,加解密,IP 当 ID
bitholic
2019-12-27 12:13:11 +08:00
redis incr 很适用: https://redis.io/commands/INCR
zoikhemlab
2019-12-27 12:56:40 +08:00
@fancy111 第一次就弹验证码,然后加,加到一百清空。
optional
2019-12-27 13:01:40 +08:00
服务端不存任何东西无法避免重放攻击,如果可以接受服务端存少量数据倒可以做的。
aver4vex
2019-12-27 13:02:19 +08:00
cookie 里计数呗,既然不想服务端计数,那就浏览器计数咯。
wangxiaoaer
2019-12-27 13:12:07 +08:00
借楼问一下,假如接口正常返回的是二进制数据(比如 img 标签的图片地址),后台检测到频繁,准备前端弹验证码? 具体怎么弹? 在原本应该返回图片的这个接口返回验证码消息,然后前端配合处理界面显示? 这样感觉不合适啊。
zchlwj
2019-12-27 14:03:14 +08:00
干嘛放数据库,redis 不香吗? HyperLogLog、布隆选择器,实现的方式多的很。
seakingii
2019-12-27 14:04:04 +08:00
肯定服务器计数啊,一个 IP 对应一个计数器,用 redis 或者自己写个使用内存存储计数的服务器,对付这种需求应该是压力很小啊.

另外这种限制客户端请求的,也可以考虑回的方案,比如限制频率,比如一秒钟最多请求多少次,一分钟最多,一天最多来替代.这种解决方案可以使用 WEB SERVER 来解决,不用自己开发.

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/632749

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX