使用节点将令牌保存在本地存储中

mon*_*ser 4 node.js express jwt

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

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

x-access-token
Run Code Online (Sandbox Code Playgroud)

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

谢谢

Bar*_*nka 15

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

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');
  }
});
Run Code Online (Sandbox Code Playgroud)

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


agm*_*984 7

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

但是,话虽如此,你们不会相信我res.cookie('auth' token)从上面的答案中找到了多长时间。我在 Google 上搜索了几个小时、Passport 文档、Express 文档、GraphQL 和身份验证/授权文档,试图找出如何以无状态方式将令牌获取到 API 。

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

将 JWT 令牌存储在 cookie 中是很好的,特别是如果您采取额外的预防措施(例如对 cookie 进行签名),我记得还可以包含一些选项来保证 cookie 的安全,这样如果“浏览器”允许访问,其他站点就无法看到它到饼干。如果 cookie 是用您的服务器机密签名的,则 cookie 中的数据根本无法更改并且仍然有效。风险始终是有人泄露了他们的令牌/cookie,如果这让您感到困扰,请研究刷新令牌。但是,API 令牌通常并且应该严格保密和安全。如果您将到期时间设置为 1 年,那么您最大的烦恼很可能是需要维护从现在开始一年后到期的 JWT 黑名单。

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

这是我用于身份验证的 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()
     }
 })
Run Code Online (Sandbox Code Playgroud)
  1. 您可以看到我正在使用 cookie 作为后备从标头设置令牌。这很好地支持了我的需求,并允许我使用任何具有无状态安全性的客户端。
  2. 我的登录用户req.person在我的视图和 GraphQL 解析器中可用。如果未设置 req.person,则将用户视为未登录。
  3. 我正在使用return req.next()which 很重要,因为next()不带参数的调用被视为“干净的转到下一个中​​间件和/或继续处理请求”。如果您包含任何字符串或对象参数,它将抛出一个错误,该错误可能会冒泡到您的错误处理中间件。你可以自己试试。放入return next('You are not authenticated.')catch 块,您将看到它在您的路线之前停止请求。
  4. 我使用return next()是因为我在路由和解析器中处理授权。它允许更多的灵活性,例如促进未经身份验证的用户访问注册和登录突变。

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

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

这是我如何使用名为的 NPM 包graphql-requesthttps : //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)}`]
     }
 })
Run Code Online (Sandbox Code Playgroud)
  1. 我包含此代码是因为没有“更高级”的 graphql-request 示例用法,到目前为止我喜欢它。它非常简洁,如果您冒险使用 React.js,可以很容易地替换为 Apollo Client。我在这里的例子也与任何研究createNetworkInterfacenew ApolloClient().