web-dev-qa-db-fra.com

AngularJS | gérer le routage avant le chargement

Je souhaite créer un contrôle d'authentification simple pour mes itinéraires par service externe.

Je définis les conditions d'accès sur l'objet route:

$routeProvider
    .when('/', {
        templateUrl: 'src/app/views/index.html',
        controller: 'indexCtrl',
        authenticated: true
    })
    .when('/login', {
        templateUrl: 'src/app/views/login.html',
        controller: 'loginCtrl',
        anonymous:  true
    })
    .otherwise({
        redirectTo: '/'
    })
;

Ensuite, je vérifie si j'ai l'autorisation dans le $routeChangeStart un événement.

$rootScope.$on('$routeChangeStart', function (event, next) {
    if(next.authenticated && !$myService.isLoggedin())
        $location.path("/login");
    else if(next.anonymous && $myService.isLoggedin())
        $location.path("/secured");
});

En fait, cela fonctionne-
si l'utilisateur n'est pas authentifié il le déplace vers la page de connexion, s'il est authentifié mais la route est pour les utilisateurs anonymes seulement il les déplace vers une autre page, etc.

MAIS- cette redirection se produit réellement après le chargement des contrôleurs et des modèles! Et cela fait que mon contrôleur fait une requête inutile à mon REST API, même si je ' ne suis pas authentifié.

Comment gérer l'itinéraire avant de le traiter?

17
Almog Baku

Ma solution combinait $locationChangeStart Et $routeChangeStart:

$rootScope.$on('$locationChangeStart', function (event) {
    //If login data not available, make sure we request for it
    if($facebook.isConnected()==null) {
        $facebook.getLoginStatus();
        event.preventDefault();
        return;
    }

    var next=parseRoute().$$route;
    if(!Auth.loginCheck(next))
        event.preventDefault();
});

J'ai copié parseRoute() de angular-route.js Pour analyser l'URL donnée à router ..

Ensuite, je crée mon gestionnaire de vérification de connexion (Auth.loginCheck) De manière à ce que s'il échoue, il retourne faux.

J'utilise également $routeChangeStart Pour gérer les événements $route.reload(), donc maintenant, après chaque modification de mon état d'authentification, je fais simplement $route.reload():

$rootScope.$on('$routeChangeStart', function (event, next) {
    Auth.loginCheck(next);
});

Enfin, je m'assure simplement que ce service personnalisé sera toujours exécuté en utilisant la méthode simple run().

Éditer:

Nous utilisons maintenant ngAuth, un module que nous avons conçu pour résoudre ce problème exact (basé sur la réponse que j'ai donnée ici auparavant).

Enfin, nous avons développé un module angulaire qui a résolu ce problème. Ce module est basé sur la réponse que j'ai publiée ici auparavant.

En raison des demandes ici, nous avons publié une version bêta qui fonctionne maintenant: http://github.com/GoDisco/ngAuth

Sentez-vous libre de l'utiliser.

16
Almog Baku

Utilisez $ routeProvider résoudre

.when('/', {
    templateUrl: 'src/app/views/index.html',
    controller: 'indexCtrl',
    resolve: function($q, $location) {
      var deferred = $q.defer(); 
      deferred.resolve();
      if (!isAuthenticated) {
         $location.path('/login');
      }

      return deferred.promise;
    }
})
23
codef0rmer

Essayez d'utiliser la propriété resolve de la route. Il résout toutes les fonctions/dépendances qui lui sont transmises avant le chargement d'un contrôleur ou d'un modèle. Dans le cas où la dépendance renvoie une promesse, jusqu'à ce que sa résolution ne soit pas chargée.

Essayez de transmettre votre service d'authentification en résolution et redirigez en cas d'échec de l'authentification.

Veuillez jeter un œil -> https://groups.google.com/forum/#!topic/angular/QtO8QoxSjYw

$ stateProvider utilise $ routeProvider en dessous. Ce wiki vous donnera plus d'informations. https://github.com/angular-ui/ui-router/wiki#resolve

1
Selvam Palanimalai

Exemple de résolution Angularjs:

.when('/profile', {
        templateUrl: 'views/profile.html',
        controller: 'ProfileCtrl',
        resolve: {
            app: function($q, $rootScope, $location) {
                var defer = $q.defer();
                if ($rootScope.currentUser == undefined) {
                    $location.path('/login');
                };
                defer.resolve();
                return defer.promise;
            }
        }
1
lsampaio

Angular-http-auth vous permet de gérer très élégamment les autorisations au niveau HTTP (lors de la récupération du modèle) et invite à la connexion si nécessaire. Tout cela sans même charger de modèle (ni contrôleur) si l'autorisation est refusée. De toute évidence, la meilleure chose que j'ai vue jusqu'à présent.

https://github.com/witoldsz/angular-http-auth

0
PowerKiKi