我有一个使用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解决这个问题的?
**** **** EDIT
好的,我们来看看吧。 我有一个在机器.10上运行的节点应用程序,同样的节点应用程序也在机器上运行.11。两台不同的机器。
我去机器.10并发送用户名密码。机器上的应用程序.10检查用户名/密码。他们都还好。机器.10创建一个jwt令牌并将其发送给我。
我现在发出一个curl请求(对一个需要有效jwt-token的资源)来加工.11并发送机器.10已经发送给我的jwt-token。机器.11不会抱怨jtw-token?它会被认为有效吗?即使它不是在机器上创建的.11?
答案 0 :(得分:6)
您问题中的两个服务器都必须能够验证令牌 - 他们必须能够生成签名。如果两个服务器共享相同的密钥(用于最初在.10上生成令牌的签名),则两者都能够验证其内容。
在下面的屏幕截图中,红色部分和紫色部分都是纯文本 - 任何人都可以阅读和修改它们。但是,蓝色部分是特殊的 - 它只能在服务器上生成,来自红色和紫色部分,使用密钥。因此,它保证红色和紫色部分不被篡改。
因此,当您将整个JTW发送回服务器时,它可以使用密钥生成蓝色部分并将其与您要发送的蓝色部分进行比较。如果他们不匹配,那么有人(非法)改变了红色或紫色部分,因此认证被拒绝。
答案 1 :(得分:2)
JWT未存储在服务器上。
当您的服务器分发JWT时,它会向客户端提供访问者的通行证,可以在请求资源时使用。只要客户端持有它并且它仍然有效(即未过期),它就可以通过请求将其显示给服务器,服务器将相应地做出响应。
服务器知道它是一个有效的传递,因为它用它的秘密签名。
至于在多台机器上运行,只要需要验证令牌的任何服务器都知道该机密,它就可以这样做。
修改以澄清上述内容
您具体询问机器A是否接受机器B发出的令牌。
接受令牌的唯一要求是验证签名,以便您可以验证签名的来源。
如果机器A和机器B共享秘密,则它们的令牌可以互换。两者完全没有区别,机器A无法判断它是否发出了令牌,或者机器B是否发出了令牌。
答案 2 :(得分:1)
无处,令牌未保存在服务器中。在documentation中,您可以阅读
身份验证:这是使用JWT的最常见方案。用户登录后,每个后续请求都将包含JWT,允许用户访问该令牌允许的路由,服务和资源。
你必须明白:
req.headers[<token_property_here>]
然后要验证,您需要运行此类代码
jwt.verify(req.headers['x-auth-token'], 'secret', function (err, res) {
if(err){
return res.json({result: 'failure'});
}
// Else do something else
}
答案 3 :(得分:1)
使用jwt,您可以将令牌保存在客户端上。通常在localStorage或sessionStorage上,每次在授权标头中发出请求时都会发送令牌
或者像stormpath推荐的方式,使用 httpOnly和安全标志将jwt保存在cookie上(阅读说明)。
因此,每当您的用户需要访问资源时,您需要检查cookie
在快递中创建jwt时,您可以使用以下方法将其保存到cookie:
res.cookie('token', jwt, { httpOnly: true, secure: true });
然后,您可以创建一个验证身份验证的中间件。
const UserAuthenticated = (req, res, next) => {
const token = req.cookies.token; //if cookie not exist, user is not authenticated (httpOnly flag)
jwt.verify(token_sent_by_used, 'secret', function (err, res) {
if (!err) {
req.token = res.validToken;
next();
} else {
res.send('Not authenticated');
}
});
};
//In your endpoint you use like:<br/>
router.get('/someEndPoint', userAuthenticated, (req, res) => {
// use the token here.
const token = req.token;
...
});
然后,当客户提出请求时,不要忘记添加 withCredentials ,以便浏览器发送Cookie。
superagent.post(url)
.withCredentials()
.send(_msg);
这就是你所需要的一切。