Мне удалось реализовать этот сценарий.
Что я сделал...
На сервере:
-Включить конечную точку API для входа. Эта конечная точка ответит веб-токеном Json в заголовке. Клиентская сторона должна перехватить его (с помощью перехватчиков $http) и сохранить (я использую локальное хранилище). Клиент также будет управлять обновленными токенами, отправленными сервером.
-При каждом запросе к серверу настройте промежуточное ПО для экспресс-проверки токена. Сначала я попробовал модуль 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):
-Включить клиентскую сторону для входа в систему. Это вызывает конечную точку сервера. Я использую базовую аутентификацию Http, закодированную с помощью base64. Вы можете использовать угловой модуль 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);
}
};
}
]);
}
]);
person
almoraleslopez
schedule
17.12.2014