10

我正在使用 JWT 保护节点 js url https://github.com/auth0/express-jwt

要创建 JWT 令牌用户会话,我只需执行以下操作:

-> auth/signup
    -> jwt.sign(user_profile,secret,expireInMinutes:{900000000 /*almost never expires*/});

或者在登录调用的情况下

 -> auth/login
        -> jwt.sign(user_profile,secret,expireInMinutes:{900000000 /*almost never expires*/});

每次调用受保护的 url 时,我都会检查req.userJWT 中间件是否自动设置。

现在我想知道:

1 - 调用 sign() 时 JWT 令牌存储在哪里?

2 - 每次调用受保护的 url 时我都必须验证()令牌吗?如果是,为什么?

3 - 当我为已签名的用户设置新令牌时,旧令牌(如果存在)会被删除吗?如果到期未设置或例如为 5 年怎么办?

4 - 为什么我不能在同一浏览器/应用程序页面上设置新令牌?如果我注册一个新令牌但令牌匹配(我检查过),我会收到无效签名错误这就像我不能在同一个浏览器上登录超过 1 个用户

4

4 回答 4

17

您一定已经使用其他用户之前的回复找到了所有之前问题的答案,但我也会尝试为其他人澄清一下:

1 - 调用 sign() 时 JWT 令牌存储在哪里?

当您调用sign时,签名的令牌不会存储在任何地方,它由sign函数返回,然后您必须将其发送给客户端以便可以存储在客户端。(例如会话存储、本地存储或 cookie)

2 - 每次调用受保护的 url 时我都必须验证()令牌吗?如果是,为什么?

是的你是。这个想法是一旦客户端拥有令牌,他们将在每次发出请求时将令牌发送到服务器。令牌由服务器处理以确定特定客户端是否已通过身份验证。

3 - 当我为已签名的用户设置新令牌时,旧令牌(如果存在)会被删除吗?如果到期未设置或例如为 5 年怎么办?

与第 1 点的答案略有相关。调用 sign 函数只会生成另一个令牌。令牌的到期存储在签名令牌本身中。因此,每次服务器从客户端获取令牌时,它都会检查过期时间作为令牌验证的一部分。需要注意的是,签名令牌只是您在签名期间作为参数传入的“user_profile”对象,以及添加到该对象的到期日期等额外字段。

因此,客户端可以在客户端存储多个令牌。只要它们还没有过期,它们都将是有效的。但是,这个想法是仅在旧令牌过期后再次通过身份验证时才向客户端发送令牌。

4 - 为什么我不能在同一个浏览器/应用程序页面上设置新令牌?如果我注册一个新令牌但令牌匹配(我检查过),我会收到无效签名错误这就像我不能在同一个浏览器上登录超过 1 个用户

这个想法是每个浏览器有 1 个用户。因为在这种情况下,浏览器是客户端。我想不出每个浏览器/客户端需要多个用户的用例,所以你显然做错了什么。这并不是说不可能将多个令牌发送到同一个浏览器/客户端。

于 2014-06-17T03:07:00.050 回答
8
  1. 您需要将令牌存储在客户端(本地存储或cookie)

  2. 是的。HTTP 是无状态的。如果您不每次都验证它,那么有人可能会在没有令牌或使用无效令牌的情况下调用您的 URL。如果您担心性能,HMACSHA256 检查非常快。

  3. 这没有意义,你一定做错了什么。

于 2014-02-20T12:45:18.920 回答
3

2 - 每次调用受保护的 url 时我都必须验证()令牌吗?如果是,为什么?

是的。但是“验证”是一个有点令人困惑的术语。

  1. 当客户端调用 /authenticate 时,服务器首先根据数据库验证用户凭据以使该用户通过身份验证。而这种“昂贵”的操作在整个令牌生命周期中只执行一次。然后,服务器准备 JSON 对象,保存有用的用户信息,并将其加密以获得 JWT 令牌。
  2. 此令牌仅向客户端发送一次,存储在浏览器中,然后在每次客户端向 /api 请求时发送回服务器。
  3. 在处理客户端/api 请求期间,服务器必须“验证”令牌的有效性(JWT 为您完成)。但这并不意味着再次针对数据库检查用户凭据。只需解密令牌以获取 JSON 对象,HMAC-SHA256 验证 - 相当快。
  4. 拥有带有有用用户信息(声明)的 JSON 对象,服务器可以允许或不允许此特定用户访问 /api 路由下的请求资源。

在令牌验证期间,不需要对用户凭据进行数据库检查,因为服务器必须信任收到并验证(成功解密)的令牌。不需要服务器会话存储来识别用户。

您可以将 JWT 令牌视为简单的会话信息,以加密形式存储在客户端上。但是,如果您需要在用户会话信息中缓存更多数据,我认为,您仍然需要在服务器上存储某种会话存储,与 cookie 中的传统会话 ID 相比,JWT 的想法几乎毫无用处。

于 2014-09-01T08:11:25.867 回答
2

对不起。这应该是对先前答案的评论,但我没有足够的代表发表评论,所以他去了

@sbaang:每次验证的另一个原因是令牌中可能有有趣的“声明2”,例如允许用户访问某些端点,而不是所有端点。因此,在每次验证中,您不仅要验证用户是否被允许访问受保护的 API,但访问特定的端点,不是基于具有有效令牌,而是基于具有专门允许它的令牌。

于 2014-06-01T17:48:21.453 回答