Подтвердить что ты не робот

Область доступа или служба в ui router onEnter для проверки доступа (auth)

Хорошо, поэтому у меня есть состояние для url/securepage, которое мне нужно проверить всякий раз, когда пользователь пытается получить к нему доступ. Поэтому я читаю, что есть функция onEnter, которую я могу использовать. Но я, похоже, не могу получить доступ к сфере охвата и услуге. Что я делаю неправильно?

        .state('securepage', {
            url: "/securepage",
            template: securepage.html,
            onEnter: function(){
                // if (!$scope.main.isAuthenticated) $state.go("/login");
                // if (!myLoginService.currentUser()) $state.go("/login");

Текущие параметры, как я вижу, это использование разрешения и/или проверка подлинности в контроллере. Но разве проверка подлинности не была бы лучше размещена в onEnter?

4b9b3361

Ответ 1

Другой подход состоял бы в том, чтобы сервис/контроллер прослушивал событие $stateChangeStart. Там вы можете проверить, требует ли вызываемое состояние аутентификации и перенаправляет запрос. Вот фрагмент:

$rootScope.$on('$stateChangeStart', function (event, nextState, currentState) {
    if (!isAuthenticated(nextState)) {
        console.debug('Could not change route! Not authenticated!');
        $rootScope.$broadcast('$stateChangeError');
        event.preventDefault();
        $state.go('login');
    }
});

isAuthenticated может содержать вызов ваших служб, проверьте nextState.data на свойства, связанные с аутентификацией, и т.д.

Ответ 2

Сегодня у меня возникла аналогичная проблема. Провел целый день и, наконец, придумал подходящее решение, отличное от тех, которые уже предложены здесь.

Моя основная цель - найти простой и эффективный способ выборочной защиты определенных определенных веб-страниц. Проверка безопасности должна выполняться до того, как HTML или любой из соответствующих контроллеров будут загружены или вызваны. Если проверка не удалась, страница может быть перенаправлена ​​в другое место без каких-либо побочных эффектов от других контроллеров.

Я попробовал другие предложенные подходы. Каждый из них имеет свой собственный набор проблем:

  • Использование OnEnter:

    • Невозможно заблокировать работу ui-router от перехода состояния при выполнении асинхронного вызова для проверки безопасности.
  • Использование $rootScope. $on ('$ stateChangeStart'):

    • Управление состояниями, в которых проверка безопасности rquire будет отделена от определений $stateProvider.state(). В идеале я бы предпочел бы все, чтобы определить определение состояния, определенного всем в одном месте. Хотя это не демонстрация, это не идеально.
    • Гораздо большая проблема заключается в том, что событие $stateChangeStart не вызывается для начальной загрузки страницы. Это шоу-шоу.

Мое решение заключается в использовании функции разрешения для определения обещания, которое заставит контроллеры представлений ждать завершения отложенных до их вызова. Эта работа идеально подходит для блокировки запуска контроллера асинхронным способом.

Здесь грубая схема кода, который я использовал:

.config(['$stateProvider', function ($stateProvider) {
    // Handler for Restricting Access to a page using the state.resolve call
    var accessRestrictionHandler = function($q, $rootScope, $state) {
            var deferred = $q.defer();

            // make sure user is logged in
            asyncCheckForLogin(function(status) {
                if (status != "Logged In") {
                    // You may save target page URL in cookie for use after login successful later
                    // To get the relative target URL, it is equal to ("#" + this.url).  
                    //      The "this" here is the current scope for the parent state structure of the resolve call.
                    $state.go("loginPage");
                }
                else    // if logged in, continue to load the controllers.  Controllers should not start till resolve() is called.
                    deferred.resolve();
            }.bind(this));

            return deferred.promise;
        };


    $stateProvider
        .state('userProfile', {
            url: '/userProfile',
            views: {
                'main': {
                    templateUrl: 'userProfile.html',
                    controller: 'userProfileCtrl'
                }
            },

            // SIMPLY add the line below to all states that you want to secure
            resolve: { loginRequired : accessRestrictionHandler } 
        })

        .state(.... some other state)
        .state(.... some other state);

}]);

Я надеюсь, что это поможет некоторым из вас там.

Ответ 3

Посмотрите issue и этот пример с их страницы github. Это должно дать вам некоторые подсказки.

Ответ 4

Поздний ответ, но я бы предпочел написать его в любом случае. Я предпочитаю не прикасаться к $rootScope, где это возможно. Вот код, который я сейчас работаю, на котором подытоживается другое решение для вашего вопроса:

state('dash', {
                url:'/',
                views:{
                    "topNav":{
                        templateUrl:"user/dash/partials/top-nav.html",
                        controller:'logoutCtrl',
                    },
                    "sideNav":{
                        templateUrl:"user/dash/partials/side-nav.html"
                    },
                    "body":{
                        templateUrl:"user/dash/partials/body.html",
                        controller:'testCtrl'
                    }
                },
                onEnter: function(Auth, $state){
                    if(!AuthSvc.isAuthenticated){
                        $state.go('login');
                    }
                }
            })

Я использую JWT для хранения токенов в localstorage с помощью ngStorage, который предоставляет услугу $localStorage, которую я вставляю в Auth factory, которую я ввел в onEnter

Ответ 5

Вероятно, вы имеете в виду

.state('securepage', {
        url: "/securepage",
        template: securepage.html,
        //this is how you actually inject things to onEnter property
        onEnter: ['$state','myLoginService',function($state,myLoginService){
             if (!$scope.main.isAuthenticated) $state.go("/login");
             if (!myLoginService.currentUser()) $state.go("/login");`}]
         ....

Ответ 6

Я использую angularjs 1.3 с ui.router 0.2.10

Я уверен, что многое изменилось с тех пор, как этот вопрос был задан, но поскольку мне пришлось это выяснить сам, и мой поиск привел меня сюда...

Что касается проверки подлинности, вы можете сделать это следующим образом:

.state('securepage', {
        url: "/securepage",
        template: securepage.html,
        onEnter: function($scope,$state,myLoginService){ //THIS IS THE CHANGE
            if (!$scope.main.isAuthenticated) $state.go("/login");
            if (!myLoginService.currentUser()) $state.go("/login");

В функции onEnter вы можете разместить довольно много провайдера/службы/ factory, и это работает из .config приложения.

Сказав это, они (производители ui-router) предлагают использовать функцию пользовательского правила, обрабатывая ее внутри. $on ('$ stateChangeStart', function (e, to) https://github.com/angular-ui/ui-router/wiki/Frequently-Asked-Questions#how-to-create-rules-to-prevent-access-to-a-state Я не знаю, почему они делают это вместо onEnter, может быть, кто-то может расширить это.