V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX  ›  greatonce  ›  全部回复第 3 页 / 共 3 页
回复总数  47
1  2  3  
@aec4d

4 位数字, 1000 次就能破,你怎么得出这个结论的?

我没有说不限制错误次数,但依赖的不是 IP 或者 hash 或者加密的 cookie ,

而是记录请求获取验证码时的 phone number 或者 email address 就可以限制了,

验证的最终目的是验证 phone number 或 email address 的有效性。


--------------------------------------------------------------------------------


根据回帖看,大家热情似乎不高啊,以下分享一下我的解决方案吧:

1.先说一下非存储型验证码的目的和动机:

之所以不希望存储类型的验证码,一来是想减少程序对外部资源的依赖,不管存储到 file 或是 redis ,这样始终会有额外的开销,需要维护额外的业务,减少对环境的依赖,这样对于后端分布式,去中心化的部署会很轻

2.不过是非存储型验证码还是存储型验证码,对试错的次数肯定需要限制的,例如,在 N 时间内连续输入 N 次,暂停向该用户开放功能权限(登录,注册,找回密码)

3.具体解决方案:

1) 首先随机生成一组 hash 值(用于后面作为 hash 的 salt )
2) 然后获取用户输入的 phone number 或 email address
3) 设置验证码有效期,这里默认为 1 小时
4) 获取时间 Y-m-d H-1 , Y-m-d H , Y-m-d H+1 生成三个时间,分别为当前时间(小时)的上一个小时,分别为当前时间(小时),分别为当前时间(小时)的下一个小时,具体为什么这样做,请看后面

创建一个迭代,使用 md5 hash

for timeItem in timeContainer:
for hash in hashSet:
codes[] = md5(hash, phone or email, timeItem) // 如果需要数字验证码则可能需要在这里过滤一下,在装到 codes



最终所有的验证码都存储到 codes ,然后随机取一个 code 作为验证码给客户端就可以了,

当客户端提交数据用于验证“验证码”是否正确的时候,继续用上面的参数生成所有的验证码,判断提交的验证码是否在 codes 里面,如果在里面就表示是有效的,否则无效。

有人可能会说这个验证码可以重复使用,没错,在一个小时内是可以重复使用的,但验证码的目的就是验证 phone number 或 email address 的有效性,所以这不是什么问题。

然后就是对试错次数的限制,如果不限制试错次数,那么验证码基本没有任何意义,尤其是 4 位数字验证码,运气差一点 9000 多次也差不多了,所以需要限制试错次数,这个不需要我再说了,大家都知道怎么做。

上面提到的三个时间,上一小时,当前小时,下一小时,之所以这样是为了防止,用户在 23 : 59 : 59 秒获取的验证码,而提交的时候是第二天了,计算不出验证码。

最后,也许你有更好的解决方案,请不吝赐教,如果以上内容有改进或任何问题,请帮助指出,谢谢。
@aec4d 这样记录错误次数有什么意义,人家每次删除 cookie 不就行了。
@aec4d 记录错误次数存储的是错误次数,不是验证码,为什么还需要 cookie 存储,感觉复杂了。
@cstabor 这是个问题,不过能接收获取到验证码就表示(手机号码,邮箱)有效,所以暂时不考虑重复使用了,当然这些都是必须要有错误次数限制的, N 时间内连续输入错误 N 次,禁止一段时间。
2016-04-22 13:21:44 +08:00
回复了 aa45942 创建的主题 CDN 就用户角度来说,我越来越不待见 CDN 了
普通用户有几个会改 hosts 的
2016-04-11 00:25:15 +08:00
回复了 whatisnew 创建的主题 PHP 纠结 php use
(new vendor\Path\Class())->method()
1. 这样写 Class()一般是构造方法需要参数的时候用于在里面传参数的, 而 new 在括号里面表明这是一个实例,所以可以调用 method ,如果是构造方法,是不会返回实例的。

(new vendor\Path\Class)->method()
2. 这种写法可以创建一个 Class 的实例,然后调用 method ,同样 new 是在括号里面,所以 new 完后是一个实例,这样的实例无法传参给构造方法。


其实这两种没有什么太难理解的,一个是 Class() 另一个是 Class 都是在()括号里面 new ,然后得到一个实例化,多练习就可以了。
很久之前的问题了,但这个也不是漏洞,主要是配置问题,匿名上 redis ,然后用命令到处一个 rsa 的 public key ,到.ssh 自然就能进去了,遇到这样的问题,怪只能怪自己不注意安全问题
1  2  3  
关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   2564 人在线   最高记录 6543   ·     Select Language
创意工作者们的社区
World is powered by solitude
VERSION: 3.9.8.5 · 19ms · UTC 16:04 · PVG 00:04 · LAX 09:04 · JFK 12:04
Developed with CodeLauncher
♥ Do have faith in what you're doing.