angularjs – 使用angular和express-jwt实现刷新令牌

我想使用angular,nodejs和express-jwt实现带有json web令牌的Sliding expiration概念.我对如何做到这一点感到困惑,并且正在努力寻找任何刷新令牌或与这些技术/框架的会话相关的其他材料的例子.

我想到的一些选择是

>初始登录后,为每个请求生成一个新令牌
>跟踪服务器端发出的令牌

但我老实说不确定,请帮忙

我设法实现了这个场景.

我做了什么……

在服务器上:

– 为登录启用API端点.此端点将在标头中使用Json Web Token进行响应.客户端必须捕获它(使用$http拦截器)并保存它(我使用本地存储).客户端还将管理服务器发送的刷新令牌.

– 对服务器的每个请求都在express中配置中间件以验证令牌.起初我尝试了express-jwt模块,但jsonwebtoken对我来说是正确的.

对于特定路由,您可能需要禁用中间件.在这种情况下登录和注销.

var jwtCheck = auth.verifyJWT;
jwtCheck.unless = unless;
app.use('/api',jwtCheck.unless({path: [
    '/api/auth/signin','/api/auth/signout'
]}));

– 中间件verifyJWT始终以标头中的令牌响应.如果需要刷新令牌,则调用刷新的函数.

jwtLib是我自己的库,其中代码用于创建,刷新和获取jwt令牌.

function(req,res,next) {
    var newToken,token = jwtLib.fetch(req.headers);

    if(token) {
        jwt.verify(token,config.jwt.secret,{
            secret: config.jwt.secret
        },function(err,decoded) {
            if(err) {
                return res.status(401).send({
                    message: 'User token is not valid'
                });
            }
            //Refresh: If the token needs to be refreshed gets the new refreshed token
            newToken = jwtLib.refreshToken(decoded);
            if(newToken) {
                // Set the JWT refreshed token in http header
                res.set('Authorization','Bearer ' + newToken);
                next();
            } else {
                res.set('Authorization','Bearer ' + token);
                next();
            }
        });
    } else {
        return res.status(401).send({
            message: 'User token is not present'
        });
    }
};

– 刷新功能(jwtLib).由于参数需要解码的令牌,请参阅上面的jsonwebtoken在调用jwt.verify()时解析解码.

如果您在登录期间创建一个有效期为4小时并且刷新到期时间为1小时(1 * 60 * 60 = 3600秒)的令牌,则表示如果用户已处于非活动状态3小时或更长时间,则会刷新令牌,但不超过4小时,因为在这种情况下验证过程将失败(1小时刷新窗口).这样可以避免在每个请求上生成新令牌,但前提是令牌将在此时间窗口中到期.

module.exports.refreshToken = function(decoded) {
    var token_exp,now,newToken;

    token_exp = decoded.exp;
    now = moment().unix().valueOf();

    if((token_exp - now) < config.jwt.TOKEN_REFRESH_EXPIRATION) {
        newToken = this.createToken(decoded.user);
        if(newToken) {
            return newToken;
        }
    } else {
       return null;
    }
};

在客户端(Angularjs):

– 允许客户端登录.这会调用服务器端点.我使用用base64编码的Http Basic Authentication.
您可以使用base64角度模块对电子邮件进行编码:密码
请注意,成功后我不会将令牌存储在localStorage或Cookie上.这将由http Interceptor管理.

//Base64 encode Basic Authorization (email:password)
$http.defaults.headers.common.Authorization = 'Basic ' + base64.encode(credentials.email + ':' + credentials.password);
return $http.post('/api/auth/signin',{skipAuthorization: true});

– 配置http拦截器以在每次请求时将令牌发送到服务器并将令牌存储在响应上.如果收到刷新的令牌,则必须存储该令牌.

// Config HTTP Interceptors
angular.module('auth').config(['$httpProvider',function($httpProvider) {
        // Set the httpProvider interceptor
        $httpProvider.interceptors.push(['$q','$location','localStorageService','jwtHelper','$injector',function($q,$location,localStorageService,jwtHelper,$injector) {
                return {
                    request: function(config) {
                        var token = localStorageService.get('authToken');
                        config.headers = config.headers || {};

                        if (token && !jwtHelper.isTokenExpired(token)) {
                            config.headers.Authorization = 'Bearer ' + token;
                        }
                        return config;
                    },requestError: function(rejection) {
                        return $q.reject(rejection);
                    },response: function(response) {
                        //JWT Token: If the token is a valid JWT token,new or refreshed,save it in the localStorage
                        var Authentication = $injector.get('Authentication'),storagedToken = localStorageService.get('authToken'),receivedToken = response.headers('Authorization');
                        if(receivedToken) {
                            receivedToken = Authentication.fetchJwt(receivedToken);
                        }
                        if(receivedToken && !jwtHelper.isTokenExpired(receivedToken) && (storagedToken !== receivedToken)) {

                            //Save Auth token to local storage
                            localStorageService.set('authToken',receivedToken);
                        }
                        return response;
                    },responseError: function(rejection) {
                        var Authentication = $injector.get('Authentication');
                        switch (rejection.status) {
                            case 401:
                                // Deauthenticate the global user
                                Authentication.signout();
                                break;
                            case 403:
                                // Add unauthorized behavIoUr
                                break;
                        }

                        return $q.reject(rejection);
                    }
                };
            }
        ]);
    }
]);

相关文章

AngularJS 是一个JavaScript 框架。它可通过 注:建议把脚本放在 元素的底部。这会提高网页加载速度,因...
angluarjs中页面初始化的时候会出现语法{{}}在页面中问题,也即是页面闪烁问题。出现这个的原因是:由于...
AngularJS 通过被称为指令的新属性来扩展 HTML。AngularJS 指令AngularJS 指令是扩展的 HTML 属性,带有...
AngularJS 使用表达式把数据绑定到 HTML。AngularJS 表达式AngularJS 表达式写在双大括号内:{{ expres...
ng-repeat 指令可以完美的显示表格。在表格中显示数据 {{ x.Name }} {{ x.Country }} 使用 CSS 样式为了...
$http是 AngularJS 中的一个核心服务,用于读取远程服务器的数据。读取 JSON 文件下是存储在web服务器上...