2015-10-20 163 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()的人也非常相關。