Как перенаправить с маршрутизатором пользовательского интерфейса, когда сеанс истекает в Firebase
Я использую Angular с Firebase и UI Router. Я использую анонимную аутентификацию. По окончании сеанса я хочу, чтобы не прошедший проверку подлинность пользователя перенаправлялся на домашнюю страницу. Я использовал генератор Yeoman Angularfire Generator в качестве модели. Но когда я использую приведенный ниже код, аутентифицированная страница не перенаправляется, когда пользователь уже на этой странице и истекает срок действия сеанса.
.config(['$urlRouterProvider', 'SECURED_ROUTES', function($urlRouterProvider, SECURED_ROUTES) {
$urlRouterProvider.whenAuthenticated = function(path, route) {
route.resolve = route.resolve || {};
route.resolve.user = ['Auth', function(Auth) {
return Auth.$requireAuth();
}];
$urlRouterProvider.when(path, route);
SECURED_ROUTES[path] = true;
return $urlRouterProvider;
};
}])
.run(['$rootScope', '$location', 'Auth', 'SECURED_ROUTES', '$state',
function($rootScope, $location, Auth, SECURED_ROUTES, $state) {
Auth.$onAuth(check);
$rootScope.$on('$stateChangeError', function(event, toState, toParams, fromState, fromParams, error) {
if (error === 'AUTH_REQUIRED') {
$state.go('home');
}
else {
console.log('authenticated');
}
});
function check(user) {
if (!user && authRequired($location.path())) {
$state.go('home');
}
}
function authRequired(path) {
return SECURED_ROUTES.hasOwnProperty(path);
}
}
])
.constant('SECURED_ROUTES', {});
маршрутизатор
.state('selection', {
url: '/selection',
authRequired: true,
views: {
'list': {
templateUrl: 'app/views/project-list.html',
controller: 'ProjectListCtrl as projectList',
resolve: {
'user': ['Auth', function(Auth) {
return Auth.$waitForAuth();
}]
}
},
'selectionlist': {
templateUrl: 'app/views/selection-list.html',
controller: 'SelectionListCtrl as selectionList'
resolve: {
'user': ['Auth', function(Auth) {
return Auth.$waitForAuth();
}]
}
}
}
})
Ответы
Ответ 1
Это обычная проблема в приложениях с одной страницей. С помощью Angular вы можете решить это с помощью перехватчика $http.
Идея заключается в том, что сеанс истек в первый раз, когда пользователю требуется какое-либо действие из бэкэнд для перенаправления на страницу входа в систему.
Истекший сеанс обнаружен из самого ответа.
Пример:
.factory('httpAuthInterceptor', function ($q) {
return {
'responseError': function (response) {
// NOTE: detect error because of unauthenticated user
if ([401, 403].indexOf(response.status) >= 0) {
// redirecting to login page
$state.go('home');
return response;
} else {
return $q.reject(rejection);
}
}
};
})
.config(function ($httpProvider) {
$httpProvider.interceptors.push('httpAuthInterceptor');
});
Ответ 2
Прочитали ли вы это?
https://www.firebase.com/docs/web/libraries/angular/guide/user-auth.html
Я прочитал раздел "Аутентификация с маршрутизаторами".
Edit
В этом случае вы можете получить значение "expires" из Auth. $getAuth() и использовать его в $timeout в $routeChangeSuccess. По существу, создание обратного отсчета до таймаута сеанса после каждого изменения маршрута... так:
$rootScope.$on("$routeChangeSuccess", function() {
var sessionTimeout = Auth.$getAuth().expires * 1000;
var d = new Date();
var n = d.getTime();
var timer = sessionTimeout - n;
console.log(timer);
$timeout(function() {
$location.path("/");
},timer);
});
Ответ 3
Как вы сказали "когда пользователь уже на этой странице и сеанс истекает". В этом случае вы можете использовать
$location.path('/home')
И для автоматического определения времени ожидания бездействия Ng-Idle, см. демонстрацию
Ответ 4
Мне удалось перенаправить работу с UI Router, изменив следующий код из моего вопроса выше:
Из этого (не работает):
function check(user) {
if (!user && authRequired($location.path())) {
$state.go('home');
}
}
К этому (рабочему):
function check(user) {
if(!user && $state.current.authRequired===true) {
$state.go('home');
}
else {console.log('logged in')}
}
Ответ 5
Вы можете использовать ajaxSetup, чтобы поймать 301 ошибку, что-то вроде этого:
$.ajaxSetup({
error : function(jqXHR, textStatus, errorThrown) {
if (jqXHR.status == 0) {
alert("Element not found.");
} else {
alert("Error: " + textStatus + ": " + errorThrown);
}
}
});