Как перенаправить с маршрутизатором пользовательского интерфейса, когда сеанс истекает в 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);
        }
    }
});