0

我在服务器端使用 Node.js 和 Passportjs 的组合,在客户端使用 Emberjs 的应用程序。我当前的身份验证策略是使用 Passport-Local 以标准的电子邮件/密码组合对用户进行身份验证,然后挂钩会话创建机制以生成身份验证令牌,将其保存到单独的表中,并传回给用户用于任何进一步受保护的路线。(在 REST 标头中传递)。

令牌的创建很好,我这样做没有问题,但是如果我需要额外的步骤,我正在努力解决。

目前,我使用node-jwt-simple生成令牌,方法是使用随机node-uuid传递作为有效负载,并将用户 UID(另一个node-uuid)作为秘密。然后我将其保存到$.cookie客户端的 a 和服务器端的表中,以及创建日期。

显然, node-jwt-simple中的步骤之一是对令牌进行编码。还提供了解码功能。我的问题是,当我进行身份验证检查时,是否需要将令牌解码为某种东西,或者只是检查用户的会话 cookie(REST 标头)是否与数据库中的令牌匹配就足够了?我不想付出所有努力来生成一个令牌,然后错过一个重要的步骤,但我没有看到如何将它解码成任何可以提供任何额外有用安全性的东西。

更新:

我想我昨晚解决了这个问题:

The solution seems to be to use the User's UID as the payload for JWT, with a static string as the secret (taken from something like a server environment variable or similar), and then only store the encoded token in the database. Pass the token back to the client for re-auth, then when the client attempts to access a protected route, they must pass their UID along with the encoded token to the server, which is then decoded, and the decoded payload compared to the UID that has been passed. If they match, the auth is successful, otherwise the token is destroyed and the user has to log in again. By doing this, it makes the store of tokens effectively useless without knowing either the Secret key, or having the User's UID, but makes the auth process more secure.

4

2 回答 2

1

如果您不验证令牌,您也可以创建一些其他随机数据用作会话 cookie,只要它是唯一的并且客户端无法猜到。

但是由于您已经付出了很多努力,您可以在令牌中编码一些有用的东西,告诉您它的有效时间,例如一个exp字段,因此您不必从数据库中读取。

我不确定我是否完全理解您的 JWT,但我看到的问题是您需要信息来解码可能不在您手边的令牌。所以你必须在你的数据库中进行搜索。

我认为使用一些随机会话密钥就足够了,例如以下函数:

var crypto = require('crypto');

/**
 * Create random bytes and encode base64url.
 * @param {int} [lengthInBytes=40] the size of the raw token in bytes
 *        (will be longer since base64url-encoded)
 * @param {function} callback node-style callback-function;
 *        data-parameter is a string w/ a shortened (no trailing ==)
 *        base64url-encoded string of the generated bytes.
 */
exports.createRandomToken = function createRandomToken(lengthInBytes, callback) {
    if (typeof lengthInBytes === 'function') {
        callback = lengthInBytes;
        lengthInBytes = 40;
    }
    crypto.randomBytes(lengthInBytes, function (ex, buf) {
        if (ex) {
            callback(ex);
            return;
        }
        callback(null, buf.toString('base64')
                          .replace(/\//g, '_')
                          .replace(/\+/g, '-')
                          .replace(/=/g, ''));
    });
};
于 2013-12-08T17:12:58.300 回答
0
  1. 将令牌的过期时间设置得尽可能短(5 分钟、30 分钟、月和年)。
  2. 每次更新旧令牌时使用刷新令牌获取新令牌并更新刷新令牌(毫无疑问,当用户登录时)
  3. 不要在令牌中存储密码、信用卡号和任何机密信息(我很确定,你知道 :))
  4. 存储检查权限(或检查 ip,例如)的所有必要信息。它适用于 REST API 和水平扩展。
于 2016-07-19T08:37:03.237 回答