2015-10-20 166 views
1

我正在使用JWT ("jsonwebtoken": "^5.4.0")使用express 4和jade。 我能够创建正确的令牌,但是如何在每次调用中传递此令牌? 我必须在哪里存储这个令牌?在标题或localStorage中?使用节点在本地存储中保存令牌

现在我使用的卷曲与邮差,并设置令牌头在

x-access-token 

我所干的事创建一个从数据库中检索令牌和在每次调用使用中间件?

感谢

回答

5

你并不需要保存并从数据库中检查令牌。这种令牌机制只能通过你的服务器进行解码,并且如果已经完成令牌有效。你想要做的代码应该看起来像。

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'); 
    } 
}); 

在这里,你可以找到非常好的文章:

+0

好的,但我怎样才能发送'var token = req.body.token || req.query.token || req.headers ['x-access-token'];'为每个请求?我怎样才能使用节点和玉器在标题中设置令牌? – monkeyUser

+0

是的,你应该发送的所有请求 –

+0

我怎样才能发送这个令牌与翡翠?在这一刻,我发送了Curl并使用了头文件,但是我想保存令牌以自动方式发送。 – monkeyUser

2

我会建议,如果你想本地存储检查了这一点:https://www.npmjs.com/package/node-localstorage

但是,随着中说,你们和女孩不会相信我从上述答案中找到res.cookie('auth' token)需要多长时间。我搜索了Google数小时,Passport文档,Express文档,GraphQL和身份验证/授权文档,以了解如何以无状态方式获取令牌给API。

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

在Cookie中存储JWT令牌是很好的,尤其是如果您采取了额外的预防措施(例如对cookie进行签名),并且我记得还有一些选项可以让cookie保持安全,以便其他站点无法看到它,浏览器“允许访问cookie。如果一个cookie与您的服务器密码签名,cookie内的数据根本无法更改并仍然有效。风险始终是有人泄漏他们的令牌/ cookie,如果这让你感到困扰,请研究刷新令牌。但是,API令牌通常应该保密并且安全。如果您将失效期限设置为1年,那么您最大的烦恼将更有可能成为维持一年后即将到期的JWT黑名单的要求。

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

这里是我的认证快递中间件:

// 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(),因为我在路由和解析器中处理授权。它允许更多的灵活性,例如便于未经身份验证的用户访问注册和登录突变。

这里是我的GraphQL端点(我用阿波罗服务器):

app.use('/graphql', bodyParser.json(), graphqlExpress((req) => { 
    const context = { 
     person: req.person 
    } 
    return { 
     schema, 
     context, 
     rootValue: null 
    } 
})) 
  1. 在我GraphQL解析器,每次查询填充req.personcontext.person其中谈到的第三个参数从上面的认证中间件。
  2. 这真是一个人需要知道的。

这里是我如何使用NPM呼包graphql-request:因为有graphql-没有 “更先进的” 示例用法 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. 我包括此代码请求,我很喜欢它。它非常简洁,如果冒险进入React.js,可以很容易地换成Apollo客户端。我的例子对于研究createNetworkInterfacenew ApolloClient()的人也非常相关。