use*_*441 7 node.js express angularjs express-jwt json-web-token
我想使用angular,nodejs和express-jwt实现带有json web令牌的Sliding expiration概念.我对如何做到这一点感到有点困惑,并且我正在努力寻找任何刷新令牌或与这些技术/框架的会话相关的其他材料的例子.
我想到的一些选择是
但老实说,我不确定,请帮忙
小智 13
我设法实现了这个场景.
我做了什么......
在服务器上:
- 为登录启用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'
]}));
Run Code Online (Sandbox Code Playgroud)
- 中间件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'
});
}
};
Run Code Online (Sandbox Code Playgroud)
- 刷新功能(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;
}
};
Run Code Online (Sandbox Code Playgroud)
在客户端(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});
Run Code Online (Sandbox Code Playgroud)
- 配置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);
}
};
}
]);
}
]);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
10147 次 |
| 最近记录: |