AngularJS – empêche les utilisateurs non authentifiés d'accéder à des itinéraires donnés

Dans mon application lorsque l'utilisateur est connecté, j'ai authService qui définit le drapeau interne est isAuthenticated . Maintenant, sur chaque changement d'itinéraire, j'ai l'auditeur attaché à l'événement $routeChangeStart qui vérifie authService.isAuthenticated() . Si non, il devrait être redirigé vers la route de connexion.

Le problème est lorsque l'utilisateur fait l'actualisation de la page (tous les paramètres authService sont perdus) et il retourne à se connecter à nouveau (tout en ayant une session valide sur le serveur). Ce n'est pas ce que je veux.

Ce que j'aimerais faire est de "bloquer" le changement d'itinéraire jusqu'à ce que j'obtienne l'information si l'utilisateur est authentifié (soit par authService qui serait immédiate, soit par le serveur si aucune information n'est disponible dans authService , par exemple après l'actualisation). J'ai une telle fonction dans 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); }); } 

Et voudrais l'utiliser dans l'auditeur d'événements.

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

Le fait est qu'il ne fonctionne pas comme prévu. J'obtiens toujours la route cible visible pendant très peu de temps, puis l'utilisateur est redirigé. Je crois que cela est dû à la nature des promesses, mais comment se débarrasser de cet effet "clignotant"?

Je ferais quelque chose comme ça dans le contrôleur de niveau supérieur , qui serait le premier contrôleur appelé lorsque la page est actualisée (excusez-moi pour les fautes de frappe dans les js, je suis un mec de 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); 

Cela garantira que le code du contrôleur ne peut pas être appelé jusqu'à ce que authCheck soit terminé.

Pour empêcher un utilisateur d'accéder aux itinéraires, vous devez faire plusieurs choses:

D'abord, définissez vos itinéraires et ajoutez une propriété comme 'accéder': allowAnonymous: true ou false

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

Deuxièmement, vous devez reconnaître un utilisateur authentifié:

Il existe plusieurs façons de le faire, mais je préfère utiliser le pouvoir d'AngularJS tout au long de l'utilisation de «Services». Par conséquent, j'ai créé un 'UserService' où nous stockons le nom d'utilisateur actuel et un indicateur de valeur s'il est authentifié ou non.

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

La dernière chose, capturer l'itinéraire modifie les événements et les traiter de manière correspondante:

Une fois que nous avons le service en place, il est temps de l'utiliser et d'implémenter la fonctionnalité de vérification pour un itinéraire. Il existe plusieurs méthodes qui interceptent l'événement de changement d'itinéraire, mais nous nous intéressons uniquement à ceux qui se produisent avant que l'utilisateur ne soit redirigé afin que nous puissions vérifier s'il est authentifié: '$ routeChangeStart', '$ locationChangeStart'. Ici, nous pouvons vérifier si l'itinéraire que l'utilisateur permet d'accéder anonymes et si l'utilisateur est connecté. Si le cas d'une défaillance, nous pouvons afficher un message d'erreur et rediriger l'utilisateur vers la page de connexion.

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

L'article complet est ici: http://net-daylight.blogspot.ro/

J'espère que cela aide!