我在服务器端使用Node.js和Passportjs的组合,在客户端使用Emberjs用于应用程序。我当前的身份验证策略是使用Passport-Local来验证具有正常电子邮件/密码组合的用户作为标准,然后挂钩会话创建机制以生成身份验证令牌,该令牌被保存到单独的表中,并传递回用户用于任何其他受保护的路线。 (在REST标头中传递)。
创建令牌很好,我这样做没有问题,但是如果我需要一个额外的步骤,我很难解决。
目前,我通过使用随机node-jwt-simple传递作为有效负载,并使用用户UID(另一个node-uuid)作为秘密,使用node-uuid生成令牌。然后,我将其保存到客户端的$.cookie
,以及服务器端的表,以及创建日期。
显然,node-jwt-simple中的一个步骤是对令牌进行编码。还提供了解码功能。我的问题是,在进行身份验证检查时,是否需要将令牌解码为某些内容,或者只是检查用户的会话cookie(REST头)是否与数据库中的令牌匹配足够?我不想全力以赴地生成一个令牌,只是为了错过了一个重要的步骤,但我没有看到我如何能将它解码成任何能提供任何额外有用安全性的东西。
更新
我想我昨晚做了这件事:
解决方案似乎是使用User的UID作为JWT的有效负载,使用静态字符串作为秘密(取自服务器环境变量或类似的东西),然后仅将编码的令牌存储在数据库中。将令牌传递回客户端以进行重新身份验证,然后当客户端尝试访问受保护的路由时,他们必须将其UID连同编码的令牌传递给服务器,然后对服务器进行解码,并将解码的有效负载与UID进行比较已经过去了。如果匹配,则auth成功,否则令牌被销毁,用户必须再次登录。 通过这样做,它使得令牌存储在没有知道密钥或具有用户的UID的情况下实际上无用,但使得身份验证过程更加安全。
答案 0 :(得分: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, ''));
});
};
答案 1 :(得分:0)