zoukankan      html  css  js  c++  java
  • 利用Redis撤销JSON Web Token产生的令牌

    利用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);
    

    如今,每次用户要请求受限的服务时,我们都须要解密其令牌,并检查令牌是否被撤销。

  • 相关阅读:
    List.add方法传入的是地址(引用)而不是值
    List (或ArrayList) 转换为int[]数组 终于搞懂了
    01背包 完全背包 状态转移方程及空间复杂度优化
    十大排序算法整理(五):归并排序实现
    OpenStack Object Storage(Swift)概述
    OpenStack 组成 架构
    云计算 概述
    OpenStack概述
    C语言位运算、移位运算 经典示例
    Python数据库访问之SQLite3、Mysql
  • 原文地址:https://www.cnblogs.com/gavanwanggw/p/7288891.html
Copyright © 2011-2022 走看看