【问题标题】:Authentication header using bearer scheme for JWT使用 JWT 的承载方案的身份验证标头
【发布时间】:2018-05-04 01:58:24
【问题描述】:

我正在使用 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 请求来尝试访问路由 /account 并且我将创建的令牌设置为标头,那么一切正常。

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 的生成和验证工作) 谢谢

【问题讨论】:

    标签: jwt passport.js express-jwt


    【解决方案1】:

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

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

    客户端存储令牌。它存储在localStoragesessionStorage 或cookie 中。各种存储位置都有pros and cons。必须对客户端进行编程以将其存储在这些地方之一,而服务器根本不存储它。如果您使用的是 Angular 或 React 等前端框架,您可以使用 Google 和搜索词(例如“angular、jwt、 storage”)找到大量信息和示例。如果您使用的是 vanilla JS,您可以按照提供的链接中的示例进行操作。基于上面的半伪代码构建:

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

    令牌在名为授权的 HTTP 标头中与每个请求一起发送。标头应具有以下格式

    Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
    

    眼睛...东西是实际的标记。在您的情况下,您可能必须使用 bearer(非大写 b),因为您已将 Passport 设置为这样。您也可以在代码中将其设为 auth.authenticate('Bearer', ... 以使其更“正确”。在较旧的文档和博客文章中,您经常可以看到 JWT 而不是 Bearer,但这并不真正遵循事实上的标准。

    如果您以这种方式发送,Passport 应该可以正确读取令牌。

    如何在客户端添加Authorization头取决于你是否使用框架,以及客户端是否是浏览器。如果您使用的是香草 JS,您可以阅读 this 链接。如果您使用的是框架,您可以谷歌“设置授权标头,角度”或类似的东西。官方文档和博客文章中通常都有大量信息。如果您使用的是前端框架,则添加 Authorization 字段的代码部分通常称为 auth 拦截器。拦截器有点像中间件。

    最后,你正在写这个:

    我应该如何使用 RestAPI 存储令牌...

    REST 并不真正关心令牌的存储方式。它在客户端完成,与 REST 无关。但是,REST 关心端点的名称。如果/login 是动词,它真的是正确的名称吗?问题被提出并回答here

    【讨论】:

      猜你喜欢
      • 2021-04-28
      • 2015-09-13
      • 2021-10-07
      • 2021-11-27
      • 2020-07-27
      • 2011-04-15
      • 2023-03-25
      • 2019-05-22
      • 1970-01-01
      相关资源
      最近更新 更多