"logout" 在 REST API 上没用吗?

Is "logout" useless on a REST API?

考虑到根据定义,REST API 是无状态的:"logout" 操作是否无用?

我的意思是,我正在使用加密的 JWT 创建 REST API。每个令牌都有一个过期时间,比方说,60 分钟。如果我在数据库 table 上保存由 API 生成的最后一个标记,"logout" 将从有效标记的 table 中删除它们。但是,如果我这样做,我明白 API 将不再是无状态的,对吧?

所以,我明白我不应该那样做。我想到的唯一解决方案是缩短 JWT 过期时间,缩短到 5 分钟,不要实施 "logout" 操作,让令牌过期。

这是正确的方法吗?

我认为你的 API 已经是有状态的,仅仅因为你有一个令牌。我也不会太在意 REST 的纯度,这意味着一切 都必须 是无状态的,不管是地狱还是水涨船高。

简单地说,如果您的应用程序需要登录,那么您需要一种注销方式。您不能实施短期到期,因为这对于 API 的消费者来说将是一种非常烦人的体验。而且你不能完全不注销,因为那是一个潜在的安全漏洞。

我有一个我支持的类似 REST API,我实现了一个注销端点,它是一个 DELETE 调用。它只是删除服务器端的令牌信息,并清除登录用户的任何类型的身份验证。

TL;DR

不,注销在 REST 中并非无用 API。其实对于需要认证的API来说,或多或少是有必要的。

自动令牌过期是一个与显式 "log out" 机制不同的问题,因此,无论您的 API是否为ReSTful。

当用户注销时,他们有意识地决定使他们的访问令牌无效 - 例如,如果他们正在使用 public 计算机或临时借用他人的设备。

自动到期用于确保用户必须以某种方式定期重新生效。这有利于服务器端安全。

访问令牌与在客户端和服务器之间共享会话状态无关 - 完全可以在没有共享状态的情况下实现访问令牌系统,并且令牌本身不实现会话状态,它仅用于验证用户是他们自称是谁。因此,访问令牌实际上与 API.

的状态无关

I mean, I'm creating a REST API using encrypted JWT

JSON Web 令牌 (JWT) 令牌将有关授权的所有数据编码到令牌本身。这种方法最重要的优点是您根本不需要后端存储来存储令牌。一个缺点是您不能轻易撤销访问令牌,因此它们通常被授予短期有效期,并且撤销是在刷新令牌处处理的。另一个缺点是,如果您在其中存储大量用户凭证信息,令牌可能会变得非常大。所以如果:

If I save on a database table the last tokens generated by the API, the "logout" would be done deleting them from the table of valid tokens

那么你将失去使用 JWT 最重要的优势,并且仍然有所有这些缺点,这对我来说似乎是不合理的。

So, I understand that I shouldn't do that. The only solution that I'm thinking is make the JWT expiration time shorter, to 5 minutes, don't implement a "logout" operation and just let the tokens expire.

Is this the correct approach?

在我看来,如果您打算使用 JWT,那是的!最好依靠令牌过期。有关此方法的更多详细信息,您可以查看 this question

Is “logout” useless on a REST API?

不管您使用的是 JWT 还是类似于计算机科学中任何其他体面的问题,答案都是 It DependsStatelessness 最重要的优点是您的 API 更具可扩展性。如果您选择此路径,可能您的 API 上的每个请求都应该经过身份验证,因为您可能需要在后端存储中搜索给定令牌或解码 JWT 令牌。因此,在这种情况下,您可能会在单个节点上付出一些性能成本,但从大局来看,您仍然具有可扩展性。我想我想说的是,如果您不需要这种可伸缩性,最好选择 Stateful 方法。否则,纯粹的 REST 原则是可行的方法。

您可以生成一个已经过期的新令牌,即过期时间为 1 秒。并将其传递给用户。任何即将到来的请求都将无效。虽然这不是最佳解决方案..

我认为这取决于您希望您的应用程序的行为,以及您需要它的安全性。您真的需要使令牌无效吗? 例如,您可以只从前端(浏览器或应用程序)中删除您的令牌。理论上,它是唯一存储该特定令牌的地方。但是,如果令牌被泄露,它在过期之前仍然有效。

如果您真的需要在服务器端使其失效,一种常见的方法是使用令牌创建一个黑名单,并不时清除过期的条目。

但是,如果您需要您的应用程序只为每个用户接受一个令牌,比如在银行应用程序中,您一次只能登录一台设备怎么办?为此,黑名单无法完成工作,因此您需要为每个用户存储一个令牌并检查传递的令牌是否相同。注销时,您只需清除该唯一条目。或者您可以只使用会话。

所以,不是没用,就是看你的应用了。

由于令牌的过期时间很短,我认为对于大多数应用程序来说,在注销时从客户端删除令牌是一个很好的解决方案。任何更多的东西都依赖于服务器,不再是无状态的。

此处好的解决方案是删除用户的令牌。 所以通常当你登录时,你会从服务器取回一个令牌并将其存储在浏览器中的 localStorage 或 sessionStorage (取决于用户希望在关闭选项卡后登录),然后发送headers 中的令牌以及您对 api.

提出的任何请求

然后如果用户注销,你甚至不联系 api(你不向你的服务器发出任何请求),你只需清除sessionStorage 或 localStorage,使用命令 localStorage.clear()sessionStorage.clear() ,然后如果用户想要发送更多请求,他将不得不重新登录 以获得另一个令牌。

此方法的一个缺点 是,例如,如果病毒在用户之前从本地或 session 存储 获取令牌注销 然后,它仍然可以像你一样发送请求,因为令牌仍然有效。 一种解决方案是在数据库中创建一个 令牌黑名单 ,如果用户注销,则将令牌存储在那里,直到令牌到期时间。然而,每次用户请求某些东西时,都必须查询数据库以检查他的令牌是否被列入黑名单,从而延长了流程,并使您的 API 有状态。