使用JWT的承载方案的认证头

时间:2017-11-20 18:42:40

标签: jwt passport.js express-jwt

我正在使用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工作的生成和验证) 谢谢

1 个答案:

答案 0 :(得分:2)

是的,发送这样的令牌就足够了。您只需要确保客户端以某种方式接收令牌。在您的特定情况下,客户端将向/login端点发送POST请求,并从对请求的响应中读取令牌。在半伪代码(客户端Javascript)中:

http.post('/login', (response) => {
  let token = response.split(' ')[1];
});

客户端存储令牌。它存储在localStoragesessionStorage或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