2013-04-09 7 views
6

W mojej aplikacji po zalogowaniu użytkownika mam authService, który ustawia wewnętrzną flagę isAuthenticated. Teraz przy każdej zmianie trasy mam słuchacza dołączonego do zdarzenia $routeChangeStart, które sprawdza authService.isAuthenticated(). Jeśli nie, powinien przekierować na trasę logowania.AngularJS - zapobiega nieuwierzytelnionemu użytkownikowi dostępu do podanych tras

Problem polega na tym, że użytkownik odświeża stronę (wszystkie ustawienia authService są tracone) i wraca do logowania (wciąż mając ważną sesję na serwerze). Nie tego chcę.

Co chcę zrobić, to "zablokować" zmianę trasy, dopóki nie otrzymam informacji, jeśli użytkownik jest uwierzytelniony (albo od authService, który byłby natychmiastowy, albo z serwera, jeśli informacje nie są dostępne w authService, np. Po odświeżeniu). Mam taką funkcję w 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); 
      }); 
     } 

i chciałby używać go w nasłuchiwania zdarzeń.

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

Chodzi o to, że nie działa zgodnie z oczekiwaniami. Wciąż dostaję widoczną trasę celu przez bardzo krótki czas, a następnie użytkownik zostaje przekierowany. Uważam, że wynika to z natury obietnic, ale jak pozbyć się tego efektu "mrugnięcia"?

Odpowiedz

6

zrobiłbym coś takiego w najwyższym poziomie kontroler, który byłby to pierwszy kontroler, który jest wywoływana gdy strona jest odświeżana (przepraszam za literówki w js, jestem coffeescript faceta):

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); 

Zapewni to, że kod kontrolera nie będzie mógł zostać wywołany, dopóki autcheCheck nie zostanie zakończony.

4

Aby uniemożliwić użytkownikowi dostępu do trasy musisz zrobić kilka rzeczy:

Najpierw ustaw swoje trasy i dodać obiekt jak „dostępu”: AllowAnonymous: Prawda lub Fałsz

// 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' }); 
}); 

II, musisz rozpoznać uwierzytelnionego użytkownika:

Istnieje kilka sposobów na to, ale wolę używać mocy AngularJS przez cały czas korzystania z "Usług". Dlatego utworzyłem "UserService", w której przechowujemy bieżącą nazwę użytkownika i wartość wskazującą, czy jest uwierzytelniona, czy nie.

// 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 
    }; 
}); 

Ostatnią rzeczą, trasa zmienia przechwytywania zdarzeń i traktować je odpowiednio:

Po mamy usługę w miejscu, to jest czas, aby użyć go i wdrożenie funkcjonalności wyboru trasy. Istnieje kilka metod przechwytywania zdarzenia zmiany trasy, ale interesują nas tylko te, które występują przed przekierowaniem użytkownika, abyśmy mogli sprawdzić, czy jest on uwierzytelniony: "$ routeChangeStart", "$ locationChangeStart". Tutaj możemy sprawdzić, czy trasa, którą użytkownik ma zamiar umożliwić anonimowy dostęp i czy użytkownik jest zalogowany. W przypadku awarii możemy wyświetlić komunikat o błędzie i przekierować użytkownika na stronę logowania.

// 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");             
        } 
       } 
      } 
     }); 
    }); 

Kompletny artykuł jest tutaj: http://net-daylight.blogspot.ro/

Nadzieję, że to pomaga!

+1

Proszę, spróbuj przeczytać ten http://stackoverflow.com/help/deleted-answers, aby uzyskać więcej informacji jak ** nie ** odpowiedzieć. Mianowicie: "Odpowiedzi, które zasadniczo nie odpowiadają na pytanie": ** niewiele więcej niż link do strony zewnętrznej ** –

Powiązane problemy