做者好牛逼啊,我不懂的他全都懂。node
Use Redis to revoke Tokens generated from jsonwebtokengit
在前面一篇文章中,我講述了怎麼用 AngularJS 和 NodeJS 經過 jsonwebtoken 作用戶驗證。有人說,就算點了 logout 按鈕, 你把 token 從 Angular 頁面的 AuthenticationService 上移掉,你仍是能用這個有效的 Token 來訪問 API,直到 jsonwebtoken 斷定它過時爲止。angularjs
爲了防止這種醜行,我決定用 Redis 數據庫 來處理 token,當用戶點了 logout 按鈕的時候。Token 只會保存一段時間,就是你用 jsonwebtoken 登錄以後,token 有效的這段時間。以後,token 會被 redis 自動刪掉。最後,咱們建立一個 nodejs 的中間件,檢查全部受限 endopoint 用的 token 是否存在 Redis 數據庫中。github
爲 NodeJS 配置 Reidsweb
首先咱們要爲 nodejs 安裝 Redis 客戶端庫,而且配置咱們的客戶端連接到 Redis 實例。當 nodejs 應用啓動的時候:redis
<!-- lang: js --> var redis = require('redis'); var redisClient = redis.createClient(6379); redisClient.on('error', function (err) { console.log('Error ' + err); }); redisClient.on('connect', function () { console.log('Redis is ready'); }); exports.redis = redis; exports.redisClient = redisClient;
而後,咱們來建立一個方法,用來檢查提供的 token 是否是被註銷了。數據庫
Token 管理和中間件json
爲了在 Redis 中保存 Token,咱們要建立一個方法來拿到請求中的 Header 的 Token 參數,而後把它做爲 Redis 的 key 保存起來。值是什麼咱們無論它。api
<!-- lang: js --> var redisClient = require('./redis_database').redisClient; var TOKEN_EXPIRATION = 60; var TOKEN_EXPIRATION_SEC = TOKEN_EXPIRATION * 60; exports.expireToken = function(headers) { var token = getToken(headers); if (token != null) { redisClient.set(token, { is_expired: true }); redisClient.expire(token, TOKEN_EXPIRATION_SEC); } }; var getToken = function(headers) { if (headers && headers.authorization) { var authorization = headers.authorization; var part = authorization.split(' '); if (part.length == 2) { var token = part[1]; return part[1]; } else { return null; } } else { return null; } };
而後,再建立一箇中間件來驗證一下 token,當用戶發起請求的時候:app
<!-- lang: js --> // Middleware for token verification exports.verifyToken = function (req, res, next) { var token = getToken(req.headers); redisClient.get(token, function (err, reply) { if (err) { console.log(err); return res.send(500); } if (reply) { res.send(401); } else { next(); } }); };
verifyToken 這個方法,是一箇中間件,用來拿到請求頭中的 token,而後在 Redis 裏面查找它。若是 token 被發現了,咱們就發 HTTP 401.不然咱們就繼續工做流,讓請求訪問 API。
咱們要在用戶點 logout 的時候,執行 expireToken 方法:
<!-- lang: js --> exports.logout = function(req, res) { if (req.user) { tokenManager.expireToken(req.headers); delete req.user; return res.send(200); } else { return res.send(401); } }
最後咱們更新路由,用上新的中間件:
<!-- lang: js --> //Login app.post('/user/signin', routes.users.signin); //Logout app.get('/user/logout', jwt({secret: secret.secretToken}), routes.users.logout); //Get all posts app.get('/post/all', jwt({secret: secret.secretToken}), tokenManager.verifyToken, routes.posts.listAll); //Create a new post app.post('/post', jwt({secret: secret.secretToken}), tokenManager.verifyToken , routes.posts.create); //Edit the post id app.put('/post', jwt({secret: secret.secretToken}), tokenManager.verifyToken, routes.posts.update); //Delete the post id app.delete('/post/:id', jwt({secret: secret.secretToken}), tokenManager.verifyToken, routes.posts.delete);
好了,如今咱們每次發送請求的時候,咱們都去解析 token, 而後看看是否是有效的。
你能夠從這裏拿到源碼