找回密码功能设计的思考

最近在看我们系统的注册登录、账户相关的内容设计。看到了找回密码这块的内容,我就想了一下,发现问题还是挺大的。

好的找回密码设计

好的找回密码的设计要至少符合以下几点:

不要有专门的表保存这些信息(主要是验证相关的信息);
注册帐号的时候使用邮箱或者手机号作为找回密码凭证(本文暂时只讨论邮箱的方式找回);
只能使用一次,并且要有过期时间;
重复发送验证token应该一样(不该每次点击重新发送都是新的,而且还都可用)。

其实最后一点有两种设计方式,一种是点击重发之后还发之前的那个,另外一种是发个新的,但是之前发的那个失效。

找回密码调研

最近也看了很多网站的找回密码的方式,其中包括但不限于腾讯、淘宝、谷歌、FB等。

首先腾讯用的是“忘了密码?”,进入之后输入qq号和验证码之后提供两种方式找回,一种是密保问题、一种是手机短信。另外腾讯的申诉找回也是相当厉害。

然后是淘宝,使用的是“忘了登录密码?”,进入之后是输入帐号及验证码,会提示几种找回方式。一是短信、二是宝令动态口令、三是人工申诉(上传证件)。

之后是谷歌,使用的是“需要帮助?”,这个提示进去之后会让选择是忘了密码还是用户名、还能选择其他问题。点击忘记密码让输入注册时的邮箱,我输入了自己的帐号,他会给我显示出我的帐号基本信息,问我最后一次记得的使用的密码,我就不输入了,然后有个“我不清楚”的按钮,点击之后让输入手机号,然后输入了之后会提示是否把验证码发到手机,同时还有我无法使用自己的手机的功能,点击之后会提示“Google 十分重视用户的安全和隐私。请回答下面一组问题,以便帮助我们判断您是该帐户的所有者而非试图盗用帐户的黑客。”这里之后就是让填写联系邮箱了,我就不继续测试了,总之谷歌的找回密码方式还是很多样的。

FB的同样也是“忘记密码?”,点击之后让输入邮箱搜索账户。之后有三种方式重置密码:使用谷歌帐号重置(不知道是不是因为我的帐号就是谷歌邮箱导致)、给我邮箱发重置链接、给我发短信重置密码。开始我以为是重置链接呢,写的就是啊,结果是让我输入六位验证码。不过他也有个连接可以认证,有两个参数,一个是u,一个是六位验证码,估计就是提交后的链接吧。应该会有防爆破机制。

验证的方式

看来现在多数都希望使用手机来验证了。毕竟邮箱可以随意注册,但是手机号一般一个人不会有太多个。

不过不管是手机还是邮箱,如果不小心,都会出现大问题。

手机方式:http://www.wooyun.org/bugs/wooyun-2010-018055
邮件方式:http://www.2cto.com/Article/201305/215934.html
http://www.wooyun.org/bugs/wooyun-2013-017322

我们这里暂时只讨论邮箱的方式找回密码。

这样看来,很多链接都是使用参数形式,一个token,一个email作为账户凭证。

其实我觉得最好不要在链接中暴露帐号信息。

rubychina上看到的一个解决方案

看到一种设计方式是给每个人一个token,并且这个token会随着salt的变化而变化,同时在获取验证码的时候,把这个token和过期时间合起来进行编码作为参数发给用户。如果需要判断一个验证链接只能用一次,可以再加一个create时间到发送给用户的链接中,同时服务器保存一个重置密码时间,用来判断是否是第一次使用,第二次则失效。

这种方式也是可以的,但是我觉得还是侵入的数据库表。而且每次查询起来也不好。

我们的现状

我们现在的处理方式有两大问题,一个是可以通过不断回放请求来达到无限发送验证码到邮箱,另一个是每次发送的验证链接都不一样并且还都可以使用。

这有几个结果,一是我们的验证链接(token)是存在redis里面的,可以无限发,如果被攻击可以导致redis崩掉。另外一个是发很多,每次都不一样,而且还都能够使用,这样用户发很多可以无限重置了,这太乱来了。

这个问题暂时还没解决,打算五一后再看,我就先不说我们的项目地址了,哈哈。

我总结的方案

由于我们本身的token(举例链接为http://xxx/qwaszx0998,其中qwaszx0998部分即为token)是临时生成并且存在redis里面的,所以我想出了如下的方式:

首先一点很重要,限制单IP重复请求是很重要的,可以做一个type_ip的key(如resetpass_1.1.1.1),每次请求value加一,设置个过期时间(比如一小时、12小时、一天等)。可以有效防刷(具体可以参考这篇文章——《Redis学习笔记(十)——过期时间、访问限制与缓存》)。
我们之前采用生成临时token为key、email为value,并且设置过期时间。每次请求新的验证链接由于没有办法获取原token,只能每次生成,也没法把以前的立刻删掉。所以我这里考虑双向缓存,即token——email和email——token双向存储,同时都有相同的过期时间,然后每次点击重新发送的时候,通过email查出是否有token,有则直接返回,没有则新建两个缓存(如果每次要求都是新的链接,老链接失效,也可以同时删掉两个缓存重建新的缓存及过期时间)。
在验证并修改密码成功之后,同时删除两个缓存。

本文原创于赵伊凡BLOG

©原创文章,转载请注明来源: 赵伊凡's Blog
©本文链接地址: 找回密码功能设计的思考

发表评论

电子邮件地址不会被公开。 必填项已用*标注