1. 程式人生 > >利用Redis撤銷JSON Web Token產生的令牌

利用Redis撤銷JSON Web Token產生的令牌

redis數據庫 pre 是否 pop 實例 撤銷 logo send .post

利用Redis撤銷JSON Web Token產生的令牌

作者:chszs。版權全部。未經允許,不得轉載。博主主頁:http://blog.csdn.net/chszs

早先的博文討論了在Angular.js和Node.js中使用jsonwebtoken實現認證授權的案例。這裏要說明一下,當用戶點擊了“註銷”button,用戶的令牌在Angular端會從授權認證服務AuthenticationService中移除,可是此令牌仍舊是有效的,還能夠被攻擊者竊取到。用於API調用,直至jsonwebtoken的有效時間結束。

為了避免此情況的發生。能夠使用Redis數據庫來存儲已撤銷的令牌——當用戶點擊註銷button時。且令牌在Redis存儲的時間與令牌在jsonwebtoken中定義的有效時間同樣。當有效時間到了後。令牌會自己主動被Redis刪除。最後,創建Node.js應用來檢查各終端上傳的令牌在Redis中是否存在。

一、在Node.js中配置Redis

首先,必須在Node.js中安裝Redisclient連接庫。並配置client能夠連接到Redis實例。

例如以下:

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;

二、令牌管理器&中間件

要保存已移除的令牌。須要創建一個函數來獲取Header的參數,並取出令牌,把它作為鍵名存儲到Redis。至於鍵值就無所謂了。

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

接下來。能夠創建一個中間件來驗證用戶提供的令牌是否有效:

// 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是一個中間件,它從請求的Header部分取出令牌,並在Redis中進行查詢。假設令牌發現了。則響應HTTP 401。

否則,繼續處理,讓用戶訪問受限制的API。

當用戶點擊註銷button時。平臺端必須調用expireToken方法。

exports.logout = function(req, res) {
    if (req.user) {
        tokenManager.expireToken(req.headers);
        delete req.user;
        return res.send(200);
    }
    else {
        return res.send(401);
    }
}

最後,讓之前開發的中間件模塊生效:

//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);

如今,每次用戶要請求受限的服務時,我們都須要解密其令牌,並檢查令牌是否被撤銷。

利用Redis撤銷JSON Web Token產生的令牌