我正在使用Express,Passport和jsonwebtoken为NodeJS中的网站构建身份验证系统。 我到处搜索,但找不到问题的解决方案。
现在我有一个身份验证控制器:
module.exports = function() {
var strategy = new BearerStrategy(params, function(payload, done) {
var decodedToken = jwtDecode(payload)
db.default.Account.find({where: {id: decodedToken.id}}).then(account =>{
if (account) {
return done(null, {
id: account.id,
role: account.role
})
} else {
return done(new Error("User not found"), null)
}
})
})
passport.use(strategy)
return {
initialize: function() {
return passport.initialize()
},
authenticate: function() {
return passport.authenticate("bearer", cfg.jwtSession)
}
}
}
我使用BearerStrategy并且此代码有效,因为我的/ login路由为用户创建了一个令牌并返回该令牌
accountController.post("/login", function(req, res) {
if (req.body.email && req.body.password) {
var accEmail = req.body.email
var accPassword = req.body.password
db.default.Account.find({where: {email: accEmail, password:
accPassword}}).then(account =>{
if (account) {
var payload = {
id: account.id,
role: account.role
}
var token = jwt.sign(payload, cfg.jwtSecret)
console.log(token)
res.status(200).json({
token: 'Bearer ' + token
})
} else {
res.sendStatus(401)
}
})
} else {
res.sendStatus(401)
}
})
如果我使用Postman发送尝试访问路由/帐户的HTTP请求,并设置为标头,则创建的令牌一切正常。
accountController.get('/account', auth.authenticate('bearer', { session: false }), function(req, res){
res.status(200).render('pages/homepage')
})
我无法回答的问题是: 使用res.json({token:token})发回令牌是不够的,令牌需要存储在某个地方,对吧?我应该如何使用RestAPI存储令牌,而且,我应该如何在每个请求中从HTTP头中的客户端发送令牌?
我愿意就如何在存储和发送JWT之间建立这种联系提出建议(因为JWT工作的生成和验证) 谢谢
答案 0 :(得分:2)
是的,发送这样的令牌就足够了。您只需要确保客户端以某种方式接收令牌。在您的特定情况下,客户端将向/login
端点发送POST请求,并从对请求的响应中读取令牌。在半伪代码(客户端Javascript)中:
http.post('/login', (response) => {
let token = response.split(' ')[1];
});
客户端存储令牌。它存储在localStorage,sessionStorage或Cookie中。各种存储空间有pros and cons。必须对客户端进行编程以将其存储在其中一个位置,并且服务器根本不存储它。如果您使用的是前端框架,例如Angular或React,您可以使用Google和搜索词来找到大量信息和示例,例如“angular,jwt,stored”。如果您使用的是vanilla JS,则可以按照提供的链接中的示例进行操作。基于上面的半伪代码:
http.post('/login', (response) => {
let token = response.split(' ')[1];
localStorage.setItem('token', token);
});
令牌与名为 Authorization 的HTTP标头中的每个请求一起发送。标题应具有以下格式
Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
ey ......东西是真正的代币。在您的情况下,您可能必须使用 bearer (非大写 b ),因为您已将Passport设置为具有这种方式。您也可以在代码中设置auth.authenticate('Bearer', ...
以使其更“正确”。在较旧的文档和博客文章中,您经常可以看到 JWT 而不是 Bearer ,但这并不符合事实上的标准。
如果以这种方式发送,Passport应该正确读取令牌。
如何在客户端中添加 Authorization 标头取决于您是否使用框架,以及客户端是否是浏览器。如果您使用的是vanilla JS,可以阅读this链接。如果您使用的是框架,则可以谷歌“设置授权标题,角度”或类似的东西。官方文档和博客文章中通常都有大量信息。如果您使用的是前端框架,那么添加 Authorization 字段的代码部分通常称为 auth interceptor 。拦截器有点像中间件。
最后,你写的是:
我应该如何使用RestAPI存储令牌......
REST并不真正关心令牌的存储方式。它是在客户端完成的,与REST无关。但是,REST关心端点的名称。如果它是动词,/login
真的是正确的名字吗?问题被提出并回答here。