我有一个使用json web令牌的节点应用程序:
var jwt = require('jsonwebtoken');
如果登录成功,则此库以这种方式创建令牌:
var payload = {mydata: 'abcd'};
var token = jwt.sign(payload, 'secret', {
expiresIn: 28800
});
return {
success: true,
message: 'Success',
token: token
};
我不明白的是令牌存储在服务器上的位置 . 如果收到令牌的同一用户调用受保护资源,那么我有这一行:
jwt.verify(token_sent_by_used, 'secret', function (err, res) {
if(!err){
res.json({result: 'success'});
}
else{
res.json({result: 'failure'});
}
}
我问这个的原因是我找不到解释如何在跨多台机器运行应用程序时处理jwt . 如果我的后端放在不同的机器上,并且用户向负载均衡器发出请求,那么请求可以命中任何机器 . 如果jwt在文件系统上写入令牌数据,那么我想如果请求命中的机器不是创建令牌的机器,则可能会出现问题 . 使用会话时,可以将会话处理程序设置为数据库 . 你如何用jwt解决这个问题?
编辑
好吧,让我们来看看 . 我有一个在机器.10上运行的节点应用程序,同样的节点应用程序也在机器上运行.11 . 两台不同的机器 .
我去机器.10并发送用户名密码 . 机器上的应用程序.10检查用户名/密码 . 他们都还好 . Machine .10创建一个jwt令牌并将其发送给我 .
我现在发出一个curl请求(对一个需要有效jwt-token的资源)来加工.11并发送机器.10已经发送给我的jwt-token . 机器.11不会抱怨jtw-token?它会被认为有效吗?即使它不是在机器上创建的.11?
4 回答
问题中的两个服务器都必须能够验证令牌 - 它们必须能够生成签名 . 如果两个服务器共享相同的密钥(用于最初在.10上生成令牌的签名),则两者都能够验证其内容 .
在下面的屏幕截图中,红色部分和紫色部分都是纯文本 - 任何人都可以阅读和修改它们 . 但是,蓝色部分是特殊的 - 它只能在服务器上生成, from 是红色和紫色部分, using 是密钥 . 因此,它保证红色和紫色部分不被篡改 .
因此,当您将整个JTW发送回服务器时,它可以使用密钥生成蓝色部分并将其与您要发送的蓝色部分进行比较 . 如果它们不匹配,则某人(非法)改变了红色或紫色部分,因此认证被拒绝 .
JWT未存储在服务器上 .
当您的服务器分发JWT时,它会向客户端提供访问者的通行证,可以在请求资源时使用 . 只要客户端保持它并且它仍然有效(即未过期),它就可以通过请求向服务器显示它,并且服务器将相应地做出响应 .
服务器知道它是一个有效的传递,因为它用它的秘密签名 .
至于在多台机器上运行,只要需要验证令牌的任何服务器都知道该机密,它就可以这样做 .
Edit to clarify the above
您具体询问机器A是否接受机器B发出的令牌 .
接受令牌的唯一要求是验证签名,以便您可以验证签名的来源 .
如果机器A和机器B共享秘密,则它们的令牌是可互换的 . 在这两者中没有任何区别,机器A将无法判断它是否发出了令牌,或机器B是否发出了令牌 .
无处,令牌未保存在服务器中 . 在documentation你可以阅读
你必须明白:
收到登录请求后,将令牌返回给用户(如果请求有效)
在每个请求中,客户端都会将令牌发回给您,您将能够验证此令牌是否与您发送的令牌相对应 . 大多数情况下,令牌将在请求标头中提供,因此在服务器端,您将能够使用
req.headers[<token_property_here>]
访问它 .然后要验证,您需要运行这种代码
使用jwt,您可以将令牌保存在客户端上 . 通常在localStorage或sessionStorage上,每次在授权标头中发出请求时都会发送令牌 .
或者像stormpath推荐的方式一样,使用 httpOnly and secure flags 将jwt保存在cookie上(阅读说明) .
因此,每次您的用户需要访问资源你需要检查一下cookie .
在快递中创建jwt时,将其保存到cookie:
然后,您可以创建一个验证身份验证的中间件 .
然后在客户端发出请求时不要忘记添加 withCredentials ,这将允许浏览器发送cookie .
这就是你所需要的一切 .