Скажем, у меня есть 4 маршрута - 2 требуют, чтобы пользователь был авторизован, 2 - нет. Моя инициализация приложения выглядит так:

        $routeProvider.when('/open1',{templateUrl:'/open1.html',controller:'Open1'});
        $routeProvider.when('/open2',{templateUrl:'/open2.html',controller:'Open2'});
        $routeProvider.when('/secure1',{templateUrl:'/secure1.html',controller:'Secure1'});
        $routeProvider.when('/secure2',{templateUrl:'/secure2.html',controller:'Secure2'});

Маршруты /open1 и /open2 открыты для всех, в то время как маршруты /secure1 и /secure2 требуют, чтобы пользователь вошел в систему и, если нет, предпринять некоторые действия, например перенаправить на вход или запустить предупреждение. Я могу определить состояние пользователя, используя мою службу Auth и позвонив, например, Auth.isLogin(). Итак, результат будет:

  • переход к /open1 и /open2 всегда переходить к шаблону и контроллеру, объявленным выше
  • если Auth.isLogin() возвращает истину, /secure1 и /secure2 переходят к вышеуказанному шаблону и контроллеру
  • если Auth.isLogin() возвращает false, /secure1 и /secure2 предпринимают другие действия, например $location.path('/login')

Я мог бы добавить логику в контроллеры Secure1 и Secure2, которая проверяет, но она повторяется и смешивает обязанности, затрудняет их тестирование и т. Д.

Есть ли способ, которым я могу использовать $routeProvider, чтобы объявить «проверьте этот маршрут и этот маршрут, а если нет, перенаправить»? Я думал как-то использовать resolve, но не совсем уверен, как с ним работать (документы по resolve не очень ясны, и есть несколько полезных примеров).

РЕДАКТИРОВАТЬ:

Судя по приведенным ниже ответам, для этого существует три основных подхода:

Второй вариант - это то, что предложили два респондента.

10
deitch 18 Ноя 2014 в 15:03

3 ответа

Лучший ответ

Как и в моих комментариях выше, существует 3 разных пути (плюс возможность использовать директиву, если вы хотите управлять ею из HTML-шаблонов). В итоге я подписался на

https://midgetontoes.com/angularjs-check-user-login/

Который по сути выглядит следующим образом:

$routeProvider.when('/secure', {
    templateUrl: '/secure.html', 
    controller: 'Secure',
    resolve:{
        loggedIn:onlyLoggedIn
    }
 });

А затем onlyLoggedIn:

var onlyLoggedIn = function ($location,$q,Auth) {
    var deferred = $q.defer();
    if (Auth.isLogin()) {
        deferred.resolve();
    } else {
        deferred.reject();
        $location.url('/login');
    }
    return deferred.promise;
};

Просто, работает как шарм. Если мне когда-нибудь понадобится директива, я перетащу ее в сервис.

13
Garf365 14 Мар 2017 в 14:17
Не могли бы вы указать, куда поместить var onlyLoggedIn, например, в какой области? Я очень новичок в этом. @deitch
 – 
timekeeper
21 Дек 2015 в 01:44
Я просто объявляю ее как функцию локальной переменной в своем app.js, а затем ссылаюсь на нее в своем $routeProvider. Но это может быть где угодно, так как вы всегда можете require() или включить его иным образом.
 – 
deitch
21 Дек 2015 в 08:43
7
Ваш URL мертв
 – 
Denny
23 Май 2016 в 11:49
URL больше не мертв, я его вернул :)
 – 
DevMoutarde
14 Мар 2017 в 15:59
Он снова мертв, так что давайте воспользуемся обходной машиной: web.archive.org/web/20160512034000/https://midgetontoes.com/…
 – 
José Roberto Araújo Júnior
4 Мар 2018 в 17:31

Это сообщение в блоге посвящено аутентификации пользователей. в AngularJS с помощью директив.

Сервис $ route выдает $ routeChangeStart перед изменением маршрута.

Если вы не используете директивы, вы можете поймать это событие, вызвав app.run (вы можете поместить его после кода, в котором вы определяете маршруты [app.config]). Например:

Для полного раскрытия информации я использую ui.router, а это адаптированный код из $ stateChangeStart Я использую в своем приложении

var app = angular.module('app');

app.config(['$routeProvider', function($routeProvider) {
    $routeProvider.when('/open1',{templateUrl:'/open1.html',controller:'Open1'});
    $routeProvider.when('/open2',{templateUrl:'/open2.html',controller:'Open2'});
    $routeProvider.when('/secure1',{templateUrl:'/secure1.html',controller:'Secure1'});
    $routeProvider.when('/secure2',{templateUrl:'/secure2.html',controller:'Secure2'});
}]);

app.run(['$rootScope', '$location', 'Auth', function($rootScope, $location, Auth) {
    $rootScope.$on('$routeChangeStart', function(event, currRoute, prevRoute){
        var logged = Auth.isLogin();

        //check if the user is going to the login page
        // i use ui.route so not exactly sure about this one but you get the picture
        var appTo = currRoute.path.indexOf('/secure') !== -1;

        if(appTo && !logged) {
            event.preventDefault();
            $location.path('/login');
        }
    });
}]);
4
MKroeders 23 Июн 2016 в 21:19
Итак, я могу использовать событие $routeChangeStart для захвата и предотвращения продолжения? Мне все равно нужно знать пути, и я бы предпочел сделать это в $routeProvider.when(), если смогу, но это сработает. Это похоже на ответ @JasonvanderZeeuw ниже. Я прочитаю сообщение в блоге, спасибо
 – 
deitch
18 Ноя 2014 в 16:58
Я бы рекомендовал маршрутизатор AngularUI, поскольку он использует состояния вместо URL-адресов. Например, состояние может быть secure.report или secure.list, а URL — /report или /list, то вы бы только проверили, содержит ли состояние secure в названии, не зная точных ссылок
 – 
vjancic
18 Ноя 2014 в 17:27
Блог интересный. Вместо того, чтобы делать это на маршруте, он предлагает установить директиву в шаблоне. Не уверен, что мне нравится такой подход, думаю, я предпочитаю его на уровне маршрута (или состояния), но идея может сработать. Я попробую.
 – 
deitch
18 Ноя 2014 в 17:58

У меня была такая же проблема, и я сделал это так:

var app = angular.module('myModule',["ui-bootstrap"]);

А затем прослушайте изменение местоположения в приложении (это также сработает при входе на страницу)

app.run(function ($rootScope, $location, $cookieStore) {
 $rootScope.$on("$locationChangeStart", function (event, next, current) {
    //Here you can check whatever you want (servercall, cookie...)
 });
}

Надеюсь, это поможет!

3
Jason van der Zeeuw 18 Ноя 2014 в 15:52
Это неплохой план, но тогда мне нужно добавить логику для каждого маршрута в обработчике событий, и как мне остановить запуск определенного маршрута?
 – 
deitch
18 Ноя 2014 в 16:03
Я добавил «бросить «остановить выполнение»;» который остановит всю активность javascript. И сделал редирект на страницу входа. В функции я проверяю, $location.path == "/signin";
 – 
Jason van der Zeeuw
18 Ноя 2014 в 16:07
Думаю, это сработает. Нет ли внутри $routeProvider ничего, что могло бы помочь?
 – 
deitch
18 Ноя 2014 в 16:08
Нет, в $routeprovider нет ничего для аутентификации, вы всегда можете взглянуть на внешний модуль, например github .com/witoldsz/angular-http-auth
 – 
Jason van der Zeeuw
18 Ноя 2014 в 16:11
В итоге я подписался на midgetontoes.com/blog/2014/08/ 31/angularjs-check-user-login с помощью разрешения. Это было самое простое.
 – 
deitch
19 Ноя 2014 в 11:22