使用节点

时间:2015-10-20 20:15:40

标签: node.js express jwt

我正在使用JWT ("jsonwebtoken": "^5.4.0")和快递4和玉。 我能够创建正确的令牌,但我如何在每次通话中传递此令牌? 我必须存储此令牌?在标题中还是在localStorage中?

现在我正在使用CURL和Postman,并在标题中设置标记

x-access-token

我是否创建了一个从数据库中检索令牌并在每次调用中使用它的中间件?

感谢

2 个答案:

答案 0 :(得分:12)

您无需保存并检查数据库中的令牌。此令牌可以仅使用您的服务器解码此类机制,如果已完成令牌有效。您想要执行的代码应如下所示。

var cookieParser = require('cookie-parser')
app.use(cookieParser())

app.get('/login', function(req, res, next) {
  var user = {name:'test'}; //!! find the user and check user from db then

    var token = jwt.sign(user, 'secret', {
            expiresInMinutes: 1440
          });

    res.cookie('auth',token);
    res.send('ok');

});

app.use(function(req, res, next) {

  var token = req.cookies.auth;

  // decode token
  if (token) {

    jwt.verify(token, 'secret', function(err, token_data) {
      if (err) {
         return res.status(403).send('Error');
      } else {
        req.user_data = token_data;
        next();
      }
    });

  } else {
    return res.status(403).send('No token');
  }
});

在这里你可以找到非常好的文章:https://scotch.io/tutorials/authenticate-a-node-js-api-with-json-web-tokens

答案 1 :(得分:3)

如果您想要本地存储空间,我建议您先检查一下:https://www.npmjs.com/package/node-localstorage

但是,有了这个说法,你们和女孩们都不会相信我从上面的答案中找到res.cookie('auth' token)需要多长时间。我花了几个小时搜索Google,Passport文档,Express文档,GraphQL和身份验证/授权文档,试图找出如何以无状态方式将令牌发送到API

我已经构建了JWT令牌安全性并使用它保护了我的GraphQL解析器,但是,我选择使用EJS和graphql-request(与Apollo Client大致相同),所以我需要找到一种方法将令牌传递给我的中间件没有使用服务器端会话。

在cookie中存储JWT令牌是很好的,特别是如果您采取额外的预防措施,例如签署cookie,我记得还有一些选项可以保持cookie的安全性,以便其他网站在&#时看不到它34;浏览器"允许访问cookie。如果cookie与您的服务器机密签名,则cookie内的数据根本无法更改并仍然有效。风险始终是有人泄露他们的令牌/ cookie,如果这困扰你,请研究刷新令牌。但是,API令牌通常应该保密并且安全。你最大的烦恼更可能是维持一个JWT黑名单的要求,如果你将到期日期定为1年,那么该名单将在一年后到期。

我只是在这里包括我的发现,因为这个问题实际上是一种罕见的资源......

  

以下是我的用于身份验证的Express中间件:

 // AUTHENTICATION
 app.use(async (req) => {
     try {
         const token = req.headers.authorization || req.cookies.auth
         const { person } = await jwt.verify(token, SECRET)
         req.person = person
         return req.next()
     } catch (e) {
         return req.next()
     }
 })
  1. 您可以看到我正在使用Cookie作为后备从标头设置令牌。这可以很好地支持我的需求,并允许我使用任何具有无状态安全性的客户端。
  2. 我的登录用户在我的视图和GraphQL解析器中以req.person的形式提供。如果未设置req.person,则将该用户视为未登录。
  3. 我正在使用return req.next(),这一点很重要,因为调用next()不带参数会被视为"干净的下一个中间件和/或继续处理请求"。如果你包含任何字符串或对象参数,它将抛出一个错误,可以冒泡到你的错误处理中间件。你可以自己试试。将return next('You are not authenticated.')放入catch块,您将看到它在您的路线前停止请求。
  4. 我使用return next(),因为我在路由和解析器中处理授权。它允许更多的灵活性,例如促进非认证用户访问注册和登录突变。
  5.   

    这是我的GraphQL端点(我使用的是Apollo Server):

     app.use('/graphql', bodyParser.json(), graphqlExpress((req) => {
         const context = {
             person: req.person
         }
         return {
             schema,
             context,
             rootValue: null
         }
     }))
    
    1. 在我的GraphQL解析器中,每个查询的第三个参数都有context.person填充req.person来自上述身份验证中间件。
    2. 这真的是一个人都需要知道的。
    3.   

      以下是我使用名为graphql-request的NPM包的方法:   https://www.npmjs.com/package/graphql-request

       app.get('/allpeople', async (req, res) => {
           try {
               const client = new GraphQLClient(GRAPHQL_ENDPOINT, {
                   headers: { Authorization: req.headers.authorization || req.cookies.auth }
               })
               const query = `query allPeople($serialNumber: String!) {
                   allPeople(serialNumber: $serialNumber) {
                       id
                       created
                       status
                       email
                   }
               }`
               const variables = {
                   serialNumber: req.person
               }
               const response = await client.request(query, variables)
               res.render('allpeople/list', { people: response.allPeople })
           } catch (e) {
               throw [`allPeople`, `${JSON.stringify(error, null, 2)}`]
           }
       })
      
      1. 我包含此代码,因为没有"更高级" graphql-request的示例用法,到目前为止我都喜欢它。它非常简洁,如果您冒险进入React.js,可以很容易地换掉Apollo Client。我的示例对于研究createNetworkInterfacenew ApolloClient()
      2. 的任何人都非常相关