透过JWT令牌验证用户请求的正确方式。

huangapple go评论82阅读模式
英文:

proper way to validate user requests via JWT token

问题

在我所有需要已登录用户的 Express Node 路由中,初始中间件是一个解码 JWT 令牌的函数。

但在令牌解码后,它会获取令牌中存储的 _idemail,然后进一步向我的数据库提供程序 MongoDB 发出 API 调用,尝试查找与 _idemail 相对应的用户。

这意味着每当用户发出请求时,我都必须查询用户是否存在于数据库中。仅仅解码 JWT 不足够,因为用户可能已被删除等情况。

这是否是通过 JWT 令牌验证用户的正确方案?

英文:

In all of my express node routes that require a logged in user, the initial middleware is a function that decodes the JWT token.

But after the token is decoded, it then grabs the _id or email stored in the token and further makes an API call to my database provider, mongoDB, and tries to find the user corresponding to the _id or email.

This means that each time a user makes a request I have to query the database for the user's existence. Just decoding the JWT isn't enough because what if the user has been deleted, etc.?

Is this the proper scheme to validate users via JWT token?

答案1

得分: 1

以下是翻译好的部分:

  1. 虽然没有一个通用的解决方案,但这对于大多数基本情况应该有效:

  2. 基于 MongoDB 或 Redis 等持久存储,跟踪用户的会话。

  3. 假设使用 MongoDB。您可以拥有一个名为 sessions 的集合,其中可以存储 { userId, token } 文档。

  4. 现在,每当用户发出请求时,请检查令牌是否已过期。如果已过期,请删除该令牌的所有文档。否则,请检查是否存在具有该令牌的会话。如果不存在,抛出错误。

  5. 当用户被删除时,使用 userId 删除该用户的所有会话。因此,如果该用户再次发出任何请求,由于会话对象不存在,中间件将失败。

英文:

There is no one generic solution to this, but this should work for most of the basic cases:

  1. Track your user's sessions, using some persistent storage like MongoDB or Redis.
  2. Assuming it's MongoDB. You can have a sessions collection, where you can store { userId, token } document.
  3. Now, whenever a user makes a request, check whether the token has expired or not, if it has expired, delete all docs from the collection, having this token. Otherwise check, whether a session with that token exists or not. If it doesn't, throw an error.
  4. When a user gets deleted, delete all the sessions for that user, using userId. So, if that user again makes any request it will fail in the middleware since the session object is absent.

答案2

得分: 0

这是一个自定义声明的问题。首先,设计一个适用于后端组件的逻辑声明原则。最安全的设计方式是将所有声明都包含在JWT中,但避免将它们暴露给浏览器。在某些情况下,您可能有理由不在JWT中包含所有声明:

  • 可能您担心将包含个人数据的JWT返回给浏览器

  • 可能授权服务器不支持从您自己的数据中发布声明

在这种情况下,您可以在第一次接收到令牌时查找自定义声明,然后为后续使用相同令牌的请求缓存结果。这段代码有点复杂,但易于管理,可以防止对数据库的过多访问。更重要的是,它可以为您的代码建立良好的结构,以便授权所需的数据对于业务逻辑而言是立即可用的。

从寿命的角度来看,这就是JWT的工作方式。应用程序使用JWT中的值直到其过期。如果您担心已删除的用户,可以使用寿命较短的JWT或减少缓存声明的生存时间。

英文:

This is a custom claims question. Start by designing a logical claims principal for the backend component. The most secure designs make all claims available to the backend in a JWT, yet avoid revealing them to the browser. In some cases, you may have reasons for not including all claims in the JWT:

  • Perhaps you have concerns about returning JWTs containing personal data to the browser

  • Perhaps the authorization server doesn't support issuing the claims from your own data

In such cases you can look up custom claims the first time a token is received, then cache results for subsequent requests with the same token. The code is a little tricky but it is easy to manage and prevents too many database hits. More importantly, it can set up your code in a good way, so that the data needed for authorization is readily available to your business logic.

From a lifetime viewpoint, this is how JWTs are meant to work. Applications use values from the JWT until it expires. If you have concerns about deleted users, use short lived JWTs or reduce the time to live for cached claims.

huangapple
  • 本文由 发表于 2023年6月6日 04:47:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/76409898.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定