496 votes

La redirection d'un certain itinéraire en fonction de la condition

Je suis en train d'écrire une petite application AngularJS qui a un login et d'un affichage principal, configurée comme suit:

$routeProvider
 .when('/main' , {templateUrl: 'partials/main.html',  controller: MainController})
 .when('/login', {templateUrl: 'partials/login.html', controller: LoginController})
 .otherwise({redirectTo: '/login'});

Mon LoginController vérifie le user/pass combinaison et définit une propriété sur l' $rootScope reflétant ce:

function LoginController($scope, $location, $rootScope) {
 $scope.attemptLogin = function() {
   if ( $scope.username == $scope.password ) { // test
        $rootScope.loggedUser = $scope.username;
        $location.path( "/main" );
    } else {
        $scope.loginError = "Invalid user/pass.";
    }
}

Tout fonctionne, mais si je accéder http://localhost/#/main - je contourner l'écran de connexion. Je voulais écrire quelque chose comme "à chaque fois que les modifications d'itinéraire, si $rootScope.loggedUser est null alors rediriger vers /login"

...

... d'attente. Puis-je écouter de changements de route en quelque sorte? Je vais poster cette question de toute façon et continuer à chercher.

515voto

st.never Points 3316

Désolé de répondre à ma propre question, mais après la plongée à travers la documentation et le code source, je pense que j'ai eu de travail. Peut-être que ce sera utile pour quelqu'un d'autre?

J'ai ajouté ce qui suit à mon module de configuration:

angular.module(...)
 .config( ['$routeProvider', function($routeProvider) {...}] )
 .run( function($rootScope, $location) {

    // register listener to watch route changes
    $rootScope.$on( "$routeChangeStart", function(event, next, current) {
      if ( $rootScope.loggedUser == null ) {
        // no logged user, we should be going to #login
        if ( next.templateUrl == "partials/login.html" ) {
          // already going to #login, no redirect needed
        } else {
          // not going to #login, we should redirect now
          $location.path( "/login" );
        }
      }         
    });
 })

La seule chose qui me semble bizarre c'est que j'ai eu à tester le nom partiel (login.html) parce que le "prochain" Route de l'objet n'a pas une url ou quelque chose d'autre. Peut-être il ya une meilleure façon?

94voto

user2949759 Points 227

Voici peut-être un plus élégant et une solution flexible permettant éventuelle de chargement de données sur le routage et les règles de routage en fonction des données, voici la solution avec 'résoudre' configuration de la propriété et des "promesses". Vous spécifiez une fonction de "résoudre" dans la configuration de routage et en fonction de la charge et de vérifier les données, faire tous les redirections. Si vous avez besoin de charger des données, vous revenez d'une promesse, si vous devez faire de la redirection de rejeter promesse de avant que. Tous les détails peuvent être trouvés sur $routerProvider et $q pages de documentation.

'use strict';

var app = angular.module('app', [])
    .config(['$routeProvider', function($routeProvider) {
        $routeProvider
            .when('/', {
                templateUrl: "login.html",
                controller: LoginController
            })
            .when('/private', {
                templateUrl: "private.html",
                controller: PrivateController,
                resolve: {
                    factory: checkRouting
                }
            })
            .when('/private/anotherpage', {
                templateUrl:"another-private.html",
                controller: AnotherPriveController,
                resolve: {
                    factory: checkRouting
                }
            })
            .otherwise({ redirectTo: '/' });
    }]);

var checkRouting= function ($q, $rootScope, $location) {
    if ($rootScope.userProfile) {
        return true;
    } else {
        var deferred = $q.defer();
        $http.post("/loadUserProfile", { userToken: "blah" })
            .success(function (response) {
                $rootScope.userProfile = response.userProfile;
                deferred.resolve(true);
            })
            .error(function () {
                deferred.reject();
                $location.path("/");
             });
        return deferred.promise;
    }
};

Pour les russes-les gens parlant il y a un post sur habr "Вариант условного раутинга в AngularJS" (ne pourrais pas poster plus de 2 liens).

61voto

user1807337 Points 497

J'ai essayé de faire la même chose. Est venu avec une autre solution, plus simple, après avoir travaillé avec un collègue. J'ai une montre jusqu'à $lieu.path(). Que fait le truc. Je commence tout juste à apprendre angularjs et de trouver que cela soit plus propre et lisible.

$scope.$watch(function() { return $location.path(); }, function(newValue, oldValue){  
    if ($scope.loggedIn == false && newValue != '/login'){  
            $location.path('/login');  
    }  
});

37voto

Oran Points 1254

Une façon différente de la mise en œuvre de connexion de redirection est d'utiliser des événements et des intercepteurs comme décrit ici. L'article décrit certains des avantages supplémentaires tels que la détection lorsqu'une connexion est nécessaire, de file d'attente de la demande, et de rejouer une fois que la connexion est réussie.

Vous pouvez essayer un travail de démonstration ici et de voir la démonstration de la source ici.

34voto

AJcodez Points 5381

1. Set global de l'utilisateur courant.

Dans votre service d'authentification, de définir l'utilisateur actuellement authentifié sur la racine de la portée.

// AuthService.js

  // auth successful
  $rootScope.user = user

2. Ensemble auth fonction sur chaque parcours protégé.

// AdminController.js

.config(function ($routeProvider) {
  $routeProvider.when('/admin', {
    controller: 'AdminController',
    auth: function (user) {
      return user && user.isAdmin
    }
  })
})

3. Vérifier auth sur chaque changement d'itinéraire.

// index.js

.run(function ($rootScope, $location) {
  $rootScope.$on('$routeChangeStart', function (ev, next, curr) {
    if (next.$$route) {
      var user = $rootScope.user
      var auth = next.$$route.auth
      if (auth && !auth(user)) { $location.path('/') }
    }
  })
})

Alternativement, vous pouvez définir des autorisations sur l'objet utilisateur et d'attribuer à chaque voie d'une permission, puis vérifier l'autorisation en cas de rappel.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X