【问题标题】:Token-based authentication and session/local storage on browsers [closed]浏览器上基于令牌的身份验证和会话/本地存储[关闭]
【发布时间】:2015-03-09 09:19:19
【问题描述】:

好的,我想实现一个使用身份验证机制来个性化网站上的用户体验的 Web 应用程序,但同时我有一些问题想要澄清。因此,一开始,用户将使用他们的用户名和密码登录(让我们暂时忘记第 3 方身份验证并假设有一个适当的注册页面),成功登录后,服务器将生成一个令牌,用于后续调用该特定用户的浏览器。在下文中,我试图验证我的理解并提出相关问题。

据我所知,在服务器端使用令牌要快得多(如果您愿意,可以减少 cpu 密集型),因为现在不必解密存储在服务器上的密码并将其与密码进行比较与请求一起发送(例如使用bcrypt),但检查要简单得多,归结为令牌是否已过期。作为一个额外的好处,用户名和密码的敏感信息不会重复传输。

检查点 1. 我们希望应用在用户自愿或意外按下“刷新/重新加载”时保持稳健,以便在刷新后仍然可以使用令牌(而不必登录再次使用凭据)。现在很清楚,要么我们必须使用 cookie(即会话),要么在客户端使用会话存储或本地存储。还有其他方法吗?据我了解,答案是否定的(是的,本地存储有不同的选项,如 Web 存储、Web SQL 数据库、索引数据库和文件访问,但这不在问题范围内)。这是对还是错?此外,在客户端处理令牌(存储/召回)最常用的做法是什么?

检查点 2。 令牌过期。据我了解,这个想法是每次使用有效令牌时,都会更新该特定令牌的到期时间(例如 7 或 10 天后)。这有一个很好的好处,即定期访问该站点的用户只需登录一次。不利的一面似乎是暗示令牌保持不变 - 可能永远 - 对于同一用户(当然,除非令牌过期)。那么问题来了,这样安全吗?这里的另一个想法是在后端更新令牌,在客户端发送更新的令牌并在浏览器的本地存储上更新令牌,而一切对最终用户都是透明的。这是一种常见的做法吗?我可以看到,现在在服务器端需要对生成的令牌保持谨慎(参见下面的场景)。是否有处理此问题的通用做法(如果需要处理)?

(假设用户 A 有两个设备 A1 和 A2 使用的令牌 TA1 将在 7 天后到期,用户 B 的设备 B1 使用令牌 TB1 将在 7 天后到期。所有令牌都存储在某种本地存储。六天后(即实际到期前一天),当用户 A 使用设备 A1 时,TA1 更新为 TA2。同样在那天 TB1 更新为 TA1。现在如果用户 A 使用设备 A2,那家伙有一个有效的令牌(TA1),但在使用 API 时将作为用户 B 进行身份验证!)

检查点 3。 我一直认为基于令牌的身份验证就是这样。通过 http 请求的标头发送的单个令牌就是这样。显然,如果还发送用户名,那么我们避免发送密码,我们也避免了我上面描述的问题场景。但是,我不太喜欢这种方法。毕竟,现在令牌充当密码。唯一节省的是解密(即 cpu 周期),同时匹配服务器端的凭据。这种方法是废话还是什么?

检查点 4. 如果将来想要为智能手机或平板电脑创建一个专用应用程序,那么(据说)在请求的标头上使用令牌要容易得多,而不是依赖 cookie 和会话(参见 cookie 容器)。目前这对我来说是次要的,但这是真的吗?

我认为上述问题与实现无关,但如果您想为开发提供指点,我将使用 node.js。

【问题讨论】:

  • 所有投票结束这个话题的人,你能写一两句话来证明你的投票吗?我的问题真的是开放式的还是与 Stack Overflow 无关?
  • 它相当广泛或基于意见。您可以查看程序员的帮助中心,看看它是否适合那里。当时我会尽量把它保留在一个问题上......

标签: node.js session authentication cookies local-storage


【解决方案1】:

1:Cookie 是客户端存储令牌的首选方法。

2:您可以重新验证用户身份并发回更新的令牌,或者只是延迟令牌的到期时间。这在很大程度上取决于您如何存储令牌,以及如何处理过期机制(例如 Mongo 的生存时间机制,或 SQL 数据库中的“expiresAt”字段等)。通过适当的令牌生成,您概述的用户劫持另一个用户会话的场景应该是不可能的。

3:令牌应该是验证用户所需的唯一。在服务器端,一旦您拥有令牌,您只需执行一个操作来检索用户对象。这在很大程度上取决于您如何设置系统。例如,您可以对其进行设置,以便将签名的令牌直接解码为用户对象,或者如果您使用持久存储来存储令牌,请使用令牌作为查询中的键。

4:发送令牌时,无论平台如何,您都最好使用请求的标头。 Cookie、本地存储等只是将令牌保存在用户设备上的工具。

如果您将 Node.js 用于您的应用程序,我建议您查看 angular-fullstack 中处理身份验证的方式,该方式使用 Passport 和与您尝试执行的操作类似的外部承载策略。

【讨论】:

  • 感谢您的宝贵时间。我当然赞成你写下一些东西所付出的努力和时间。在这个过程中对我来说唯一有趣的是 (1) 建议使用 cookie 以便我们可以将令牌存储在客户端(因此 cookie 将永远来回传输),而 (4) 建议发送标头上的标记(这也是我更喜欢的)。我知道出于与旧 IE 变体(而不是本地存储)的兼容性原因,cookie 可能更可取,但这对我来说似乎是错误的。无论如何,感谢您的宝贵时间。
  • 我还不会接受,因为我想看到一两条额外的评论。如果没有人写下什么,我会接受你的回答。
  • 就 cookie 而言,您是对的,其中很多与兼容性问题有关,在大多数情况下并非完全必要。但是,这是您可以在客户端控制的东西,因为您可以检查会话/本地存储之类的东西是否可用,如果可用,则使用它,否则默认为 cookie。
  • 已接受。感谢您的宝贵时间。
猜你喜欢
  • 2018-01-08
  • 2013-06-27
  • 2011-03-07
  • 2021-01-25
  • 2015-12-24
  • 2023-02-05
  • 2020-01-22
  • 2016-12-18
  • 2018-06-10
相关资源
最近更新 更多