What is the best way to implement “remember me” for a website?
我希望我的网站有一个用户可以点击的复选框,这样他们就不必每次访问我的网站都登录。我知道我需要在他们的计算机上存储一个cookie来实现这一点,但是cookie中应该包含什么?
此外,是否有一些常见的错误需要注意,以防止此cookie出现安全漏洞,这在仍然提供"记住我"功能的情况下是可以避免的?
- 检查stackoverflow.com/questions/549/…(顶部答案第二部分)
- 如果您使用的是ASP.NET,请查看codeproject.com/articles/779844/remember-me
- 在security se~security.stackexchange.com/questions/19676/&hellip中有一些非常有用的信息。
改进的持久登录cookie最佳实践
您可以使用此处描述的最佳实践(2006年)或此处描述的更新策略(2015年):
当用户成功登录并选中了RememberMe时,除了标准会话管理cookie外,还会发出一个登录cookie。
登录cookie包含一个序列标识符和一个令牌。序列和标记是来自适当大空间的不可测随机数。两者都存储在一个数据库表中,标记被散列(sha256很好)。
当非登录用户访问站点并显示登录cookie时,将在数据库中查找序列标识符。
如果序列标识符存在,并且令牌的散列与该序列标识符的散列匹配,则认为用户已通过身份验证。生成新的令牌,在旧记录上存储令牌的新哈希,并向用户发出新的登录cookie(可以重新使用序列标识符)。
如果序列存在但令牌不匹配,则假定为盗窃。用户将收到一个措辞强烈的警告,并删除用户记住的所有会话。
如果用户名和序列不存在,则忽略登录cookie。
这种方法提供了深度防御。如果有人设法泄漏了数据库表,它不会为攻击者提供一扇模拟用户的大门。
- 另请参阅:stackoverflow.com/questions/549/…您不应该阅读"改进"版本
- 问题在于你在cookie中暴露了用户名,尽管这是Gmail所做的。为什么同时需要序列ID和令牌?一个大一点的代币行吗?
- @雅尔:不,不会好的,这篇文章描述了为什么
- @谢鲁维姆,谢谢你。为什么?
- @雅:这篇文章详细描述了。这个系列被用来减轻cookie被盗的后果。
- 还要确保更改用户密码或密码恢复信息需要原始密码。如果cookie被破坏,攻击者无法阻止原始所有者访问帐户。
- 有人能解释序列标识符什么时候会改变吗?如果没有,那么将用户名加密,令牌就足够了吗?
- 序列标识符的整个概念没有如本文所述的那样有意义。
- @当提供有效的用户名/密码组合来验证用户身份(而不是令牌)时,将发出新的序列标识符。这将启动一系列新的随机令牌,用于标识此特定(长)登录会话。
- @Tvanfosson…你为什么需要这个?只需生成一个新的唯一令牌……没有理由一个用户不能拥有多个令牌……每个登录一个……令牌A、令牌B、令牌C……不需要序列标识符。
- 另外,对于这个模型,防止攻击者窃取的方法是什么,而不是将cookie放在他的计算机上,然后从被黑客攻击的计算机上删除cookie。他的电脑会不会得到认证,并根据需要进行更新,而被黑客入侵的电脑永远不会知道?唯一的改变是,被黑客攻击的计算机用户必须再次登录并设置"记住我"。被黑客攻击的用户是否认识到这一点是不确定的。
- 您需要添加计算机特性…为了唯一性,可以添加一个MAC地址或一组其他特性,如用户代理、屏幕分辨率等。
- 使用ID而不是用户名是否更稳定,这样您就不必担心任何区分大小写的问题以及字符串带来的所有其他问题了?
- 我发布了一个关于这个答案的问题:stackoverflow.com/questions/10957584/…
- @Hiroprotagonist系列标识符用于防止DoS攻击。如果没有它,我可以用每个用户名和一个无效的令牌快速编写一个脚本来攻击您的站点,从而注销站点上的所有人。
- 为什么不添加用户名的哈希?
- 如果只在步骤3.1中生成了一个新的令牌(这只发生在未登录的用户身上),那么新的令牌是否会随登录用户的每个请求一起发送呢?这就为截取数据包留下了很多机会。是否可以将此cookie配置为仅在未登录时发送?
- @Kingcoyote将cookie的路径设置为自动登录页面的路径。
- 我昨天实现了这个解决方案,我认为它工作得很好,没有提到的是如何处理数据库中的"孤立"身份验证信息。当用户手动清除他的cookie缓存时,数据库中的身份验证信息将被孤立。也许在表中实现一个自动更新时间戳并手动删除某个时间段内的所有身份验证数据是一个好主意。
- @克里斯莫奇尼已经有一段时间了,但我希望没事。你能解释一下为什么序列标识符有助于防止DOS攻击吗?和Hiroprotagonist一样,我看不出使用较长的令牌和序列标识符+令牌之间有什么区别。
- @如果你只是使用一个长令牌,并且在任何无效令牌到达时销毁用户的所有会话,我可以编写一个脚本,用每个用户名和令牌的所有0访问你的站点,以注销所有用户。在一个循环中运行它,没有人可以有意义地登录。但是,如果在服务器对抗会话之前需要一个有效的序列令牌,则可以防止DOS攻击。
- @yar包含电子邮件ID是为了保持唯一性,因为可能会为两个不同的帐户生成相同的令牌。
- @克里斯莫奇尼:为什么他们会被注销?我只看到"记忆会话被删除",这意味着您可以有效地执行记忆功能,但不能执行整个身份验证,对吗?
- 改进后的版本实际上并没有提供额外的安全级别,只是一种错觉而已。正如@jens roland所说,几乎所有允许用户窃取cookie的攻击向量都允许从被黑客攻击的计算机中删除cookie。
- 你能提供一个简单的版本,只有用户名+令牌,只是为了了解基础知识吗?(然后我可以添加这个系列)
- 如果用户的Internet连接不好,在接收新令牌时,这可能是一个问题吗?例如,用户请求使用令牌登录,Internet连接断开,服务器生成新令牌,用户未收到新令牌,用户使用旧令牌重试,这被视为黑客尝试,所有令牌都从数据库中删除,用户现在必须再次登录。
- 当您在地址栏中键入URL时,chrome会发送一个加载请求。这可能会导致remember me代码过早执行,当用户在地址栏中按Enter键时,该代码将使令牌在执行实际请求时失效。除了使用静态cookie之外,我没有看到一个简单的方法来解决这个问题,它在随后的登录过程中不会改变。还有人遇到这个问题吗?
- 这个解决方案是错误的,它不处理cunconcurrency:如果两个remember-me身份验证请求同时到达,使用相同的remember-me cookie,第一个请求成功并更改令牌,第二个请求导致不连续的完全身份验证和错误的警报(因为令牌已经被第一个请求更改)。(当浏览器启动并在两个浏览器选项卡中恢复站点时,可能会发生这种情况。)
- 在这种情况下,竞争条件比防止重播攻击更不重要。比赛条件:必须手动重新登录。重放攻击:令牌变得更适合窃取,因为它们不是暂时的。
- 向用户显示错误警报是非常不可取的。无论是因为Slobo、Craigrs84或Frogga提到的原因,此解决方案都会定期生成这些错误警报。
- 这个问题和答案很奇怪。没有提到是否应该将用户ID存储在客户机上,并与序列和令牌一起发送以进行验证。所以读者必须猜测这个系列可能是用户的替代品。第二个问题,问题是关闭的,所以唯一的信息来源是评论。第三个问题:并发性。它并不小,因为同时打开两个标签中的同一个站点非常频繁。即使是1%的时间,你也不会希望它失败。
- @frogga一个潜在的解决方案是在数据库中的每个会话中存储2个令牌(以前的和现在的)。如果接收到前一个电流,则表示未接收到电流,生成并返回新的电流。如果接收到电流,则电流变为前一个电流,生成并返回新的电流。但是,这并不能解决上述并发问题。
- "生成新令牌"…!为什么?为什么每次我都要创建一个新的cookie?
- 下面是一个golang实现:github.com/janekolszak/rememberme
- 回答说:"如果序列标识符存在,并且令牌的散列与该序列标识符的散列匹配,则认为用户已通过身份验证。"序列标识符没有散列,因此这没有意义。我认为他想说的是,"如果序列标识符存在于cookie中,而cookie中令牌的散列与存储在表中的令牌的散列和序列标识符一起,则认为用户已通过身份验证。"
- 因为理解需要为cookie名称和值创建哈希。都是用mysql写的。在登录页面,检查是否存在具有特定名称(哈希)的cookie。如果是,那么选择mysql,其中cookie名称和值与mysql中的相同。如果是,那么从mysql获取用户ID并设置该用户登录的会话,ID是mysql ID。是否正确?据了解,cookie标识符是cookie名称?
- 我想知道为什么我需要2个随机数的单一代币?如果有人说安全,那么我会说,那就让我们使用100个随机标记。
- 你们应该阅读这篇文章的链接,它告诉我们如果一个黑客访问了一个受害者的帐户,那么这个黑客就没有1,受害者就没有0,当受害者访问他的帐户时,他知道有人访问他的帐户是因为他没有0(无效的令牌和有效的系列)。
- 你更新了444:d
- "如果有人设法泄漏数据库表,它不会为攻击者提供一扇模拟用户的大门",它确实这样做了。但直到用户再次使用该站点。如果有人在用户不访问该站点时窃取序列标识符和令牌,那么它的工作方式就像一个符咒。
- @斯隆,我也会问同样的问题。您完全正确,如果用户打开了两个选项卡,则将从两个选项卡中注销(即使在第二个选项卡中对其进行了身份验证)。我建议在每次登录或注销时更新令牌,而不是每次调用时更新令牌。
- @但是,DRINOVC不会工作,因为当用户访问数据库表时,他们将得到的只是序列和哈希标记。因此,如果他们创建了两个cookie,每个cookie对应一个cookie,那么令牌将始终失败,因为他们拥有原始cookie的哈希版本。
- @Chrismoschini系列如何防止DoS攻击?什么能阻止我写一个脚本来尝试序列cookie的所有变体,令牌刚刚设置为"1",它将通过并注销所有人。
- @如果你只是把rememberme令牌当作密码,并且只存储它的hmac,那么就不是drinovc了。
我会存储一个用户ID和一个令牌。当用户返回站点时,将这两条信息与持久性的信息(如数据库条目)进行比较。
至于安全性,不要把任何东西放在里面,让别人修改cookie以获得额外的好处。例如,不要存储他们的用户组或密码。任何可以被修改的规避安全的东西都不应该存储在cookie中。
存储他们的用户名和一个remembertoken。当他们登录"记住我"复选框时,生成一个新的"记住我"(它使标记为"记住我"的任何其他机器失效)。
当他们返回时,通过rememberMe令牌查找它们,并确保用户ID匹配。
- 这可以在几秒钟内被残忍地强迫。我只需将我的用户ID设置为1,然后强制使用所有令牌。它会在几秒钟内让我进入
我亲自调查了持续的会话,发现这根本不值得承担安全风险。如果必须使用它,那么可以使用它,但是您应该只考虑这样一个会话的弱身份验证,并强制对攻击者有价值的任何内容进行新的登录。
当然,原因是包含持久会话的cookie很容易被盗。
4种偷你饼干的方法(摘自Jens Roland在@splattne页上的评论,他的答案基于此):
通过不安全线路拦截(包嗅探/会话劫持)
直接访问用户的浏览器(通过恶意软件或物理访问框)
从服务器数据库中读取(可能是SQL注入,但可能是任何东西)
通过XSS黑客(或类似的客户端攻击)
- 1。HTTPS旨在防止这种情况发生。2。保持登录不是这里的安全问题,你有更大的问题。三。与2相同。4。这可以通过访问控制策略和良好的输入环境卫生来防止;如果不采取这些步骤,您将再次遇到比保持登录更大的问题。