2013-04-09 10 views
6

Nella mia app quando l'utente ha effettuato l'accesso, ho authService che imposta la bandiera interna isAuthenticated. Ora su ogni cambio di percorso ho ascoltatore collegato all'evento $routeChangeStart che controlla authService.isAuthenticated(). Se no, dovrebbe reindirizzare al percorso di accesso.AngularJS - impedisce all'utente non autenticato di accedere a determinate route

Il problema si verifica quando l'utente effettua l'aggiornamento della pagina (tutte le impostazioni authService vengono perse) e ritorna di nuovo al login (pur mantenendo una sessione valida sul server). Questo non è quello che voglio.

Quello che mi piacerebbe fare è "bloccare" il cambio di rotta fino a quando non ottengo le informazioni se l'utente è autenticato (o da authService che sarebbe immediato, o dal server se nessuna informazione è disponibile in authService, ad esempio dopo l'aggiornamento). Ho una tale funzione nel authService

 // returns promise 
     currentUser: function() { 
      if (authService.isAuthenticated()) { 
       return $q.when(authService.loggedUser); 
      } 
      return $http.get('/session').then(function(response) { 
       authService.loggedUser = response.user; 
       return $q.when(authService.loggedUser); 
      }); 
     } 

e vorrei usarlo in listener di eventi.

$rootScope.$on("$routeChangeStart", function (event, next, current) { 
     if(isRouteRestricted(next)) { 
      authService.currentUser().then(null, function() { 
       $location.path('/login'); 
      }); 
     } 
    }); 

Il fatto è che non funziona come previsto. Ricevo ancora la rotta target visibile per un tempo molto breve, quindi l'utente viene reindirizzato. Credo che sia dovuto alla natura delle promesse, ma come sbarazzarsi di questo effetto "blink"?

risposta

6

farei qualcosa di simile nel alto regolatore di livello, che sarebbe il primo controller che si chiama quando la pagina viene aggiornata (scusa per errori di battitura nei js, io sono un ragazzo CoffeeScript):

var authCheck = function (event, next, current) { 
    if(isRouteRestricted(next)) { 
     authService.currentUser().then(null, function() { 
      $location.path('/login'); 
     }); 
    } 
} 

authCheck(null, populateNextSomehow).then(function() { 
    // all of your controller code, probably in a separate function 
}); 

$rootScope.$on("$routeChangeStart", authCheck); 

Ciò garantisce che il codice del controller non possa essere chiamato fino a quando authCheck non è completo.

4

Per impedire a un utente per l'accesso ai percorsi si deve fare diverse cose:

In primo luogo, impostare i percorsi e aggiungere una proprietà come 'accesso': AllowAnonymous: vero o falso

// in app.js 
var myApp = angular.module('myApp',['ngResource', 'ngCookies', 'ngRoute']);  
myApp.config(function ($httpProvider, $routeProvider) { 
    window.routes = { 
     '/Login': 
      { templateUrl: '/Account/Login', 
      controller: 'AccountController', 
      access : {allowAnonymous : true} 
      }, 
     '/MembersPage': 
      { templateUrl: '/Home/SomePage, 
      controller: SomePageController', 
      access: {allowAnonymous:false} 
      } 
     }; 

     for (var path in window.routes) { 
      $routeProvider.when(path, window.routes[path]); 
    } 
    $routeProvider.otherwise({ redirectTo: '/Login' }); 
}); 

In secondo luogo, è necessario riconoscere un utente autenticato:

Ci sono diversi modi per farlo, ma preferisco usare la potenza di AngularJS per l'uso di "Servizi". Pertanto, ho creato un 'UserService' in cui memorizziamo il nome utente corrente e un valore che indica se è autenticato o meno.

// in UserService.js 
myApp.factory('userService', function() { 
var user = { 
    isLogged: false, 
    username: '',  
}; 

var reset = function() { 
    user.isLogged = false; 
    user.username = ''; 
}; 

return { 
    user: user, 
    reset : reset 
    }; 
}); 

Ultima cosa, percorso di acquisizione cambia gli eventi e trattarli di conseguenza:

Dopo abbiamo il servizio in atto, è il momento di usarlo e implementare la funzionalità di controllo per un percorso. Esistono diversi metodi che intercettano l'evento di modifica dell'itinerario, ma siamo interessati solo a quelli che si verificano prima che l'utente venisse reindirizzato in modo da poter verificare se è autenticato: '$ routeChangeStart', '$ locationChangeStart'. Qui possiamo controllare se il percorso che l'utente sta per consentire l'accesso anonimo e se l'utente è loggato. Se il caso di errore, possiamo visualizzare un messaggio di errore e reindirizzare l'utente alla pagina di accesso.

// in RootController.js 
myApp.controller('RootController', 
function ($scope, $route, $routeParams, $location, $rootScope, authenticationService, 
userService, toaster) { 
$scope.user = userService.user; 
$scope.$on('$routeChangeStart', function (e, next, current) {    
    if (next.access != undefined && !next.access.allowAnonymous && !$scope.user.isLogged) { 
       $location.path("/Login");     
      } 
     }); 

     $scope.logout = function() { 
      authenticationService.logout() 
       .success(function (response) { 
        userService.reset();      
        toaster.pop("info", 'You are logged out.', ''); 
       }); 
     }; 

$rootScope.$on("$locationChangeStart", function (event, next, current) { 
    for (var i in window.routes) { 
    if (next.indexOf(i) != -1) { 
    if (!window.routes[i].access.allowAnonymous && !userService.user.isLogged) { 
      toaster.pop("error", 'You are not logged in!', ''); 
      $location.path("/Login");             
        } 
       } 
      } 
     }); 
    }); 

articolo completo e 'qui: http://net-daylight.blogspot.ro/

Speranza che aiuta!

+1

Per favore, prova a leggere questo http://stackoverflow.com/help/deleted-answers, per capire meglio come ** non ** rispondere. Vale a dire: "Risposte che non rispondono fondamentalmente alla domanda": ** a malapena più di un link a un sito esterno ** –

Problemi correlati