用 Redis 处理 jsonwebtoken 生成的 Token

做者好牛逼啊,我不懂的他全都懂。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, 而后看看是否是有效的。

你能够从这里拿到源码

相关文章
相关标签/搜索