本文讨论几种“记住我”功能的实现方式。
原理:用户登录后,服务端为用户生成一个Token,并放入客户端Cookie中。下次用户登录,服务端验证Cookie中的Token并自动登录。
- 简单的Token生成方法
Token=MD5Hex(username+分隔符+expiryTime+分隔符+password)
CookieValue=Base64(username+分隔符+expiryTime+分隔符+Token)
username:用户名。
password:用户密码。
expiryTime:Token的失效时间,以毫秒表示。
该方法生成的Token不需要持久化,每次生成时失效时间不同,可保证Token不同(也可以在Token中增加一些变量,如系统配置的key)。
用户第一次登陆时生成Token;
第二次打开系统时,根据CookieValue中username查询数据库,并重新生成Token,验证用户提交Token是否正确,如果正确成功登入系统,如果不正确,调整到登陆页面。
-
存在安全问题。
当用户Cookie被窃取(HttpOnly增加安全性),任何用户都可以在Token失效之前登录。发现被盗用,可以修改password来使Token失效,或者系统在用户每次登入系统时都重新生成Token。 -
缺点:由于Token没有持久化,所以需要从已知的变量(如username、password、expiryTime)重新生成来验证,password即使加密放入前台,也不是一个好的解决方法。纵然不使用password,也需要其他变量来保证Token的可靠性。
-
持久化的Token生成方法
Token的生成规则可以自定义,只要保证每次username的Token不一样就可,例如采用16位随机数(如Java的SecureRandom)。规则同上面类似,只是将Token与用户信息解耦。但是安全问题依旧存在。
持久化Token生成方法并验证Cookie是否被窃取
Token:随机生成策略,只要保证username唯一性。
series:登录序列号,随机生成策略。用户输入用户名和密码登录时,该值重新生成。使用remember-me功能,该值保持不变,重新生成Token。
expiryTime:Token过期时间。
1)每次用户选择记住我并登录后,都重新随机生成series、Token,保存到数据库和前端Cookie中。
2)下一次用户再次访问系统,
情况一:前台Cookie中保存的series值在数据库中不存在,跳转到登录页面。
情况二:series、Token与数据库中一致,则仍为合法用户,并保持series不变,重新随机生成Token,覆盖前台Cookie值。
情况三:series在数据库中存在,但Token不一致,说明Cookie被窃取。
情况一、同用户相同浏览器访问系统
情况一、同用户相同浏览器访问系统情况二、同用户不同浏览器访问系统
情况二、同用户不同浏览器访问系统
情况三、Cookie被盗
情况三、Cookie被盗安全问题依然存在。
a. 可以考虑用户访问等级,如用户名密码登录级别最高,而对于Token记住我登录次之,对于一些重要的业务操作时(如支付),还是需要进行用户身份认证。
b. 还可以考虑用户IP,但现在移动用户,经常切换WiFi和网络,所以IP也会发生变化。例如手机银行(如招行客户端)切换网络后,需要重新登录,提高安全性。
c. 还可以考虑,用户常用IP、城市等安全策略。
网友评论