Ok, j'ai donc un état pour l'URL "/ securepage" que je dois vérifier chaque fois qu'un utilisateur essaie d'y accéder. J'ai donc lu une fonction onEnter que je peux utiliser. Mais je ne peux pas sembler avoir la portée ni un service à partir de là. Qu'est-ce que je fais mal?
.state('securepage', {
url: "/securepage",
template: securepage.html,
onEnter: function(){
// if (!$scope.main.isAuthenticated) $state.go("/login");
// if (!myLoginService.currentUser()) $state.go("/login");
Les options actuelles, à mon avis, consistent à utiliser résoudre et/ou vérifier l’authentification dans le contrôleur. Mais un contrôle d'authentification ne serait-il pas mieux placé dans onEnter?
J'ai rencontré un problème similaire aujourd'hui. Nous avons passé une journée entière et avons finalement trouvé une solution viable autre que celles déjà suggérées ici.
Mon objectif principal est de trouver un moyen simple et efficace de sécuriser sélectivement certaines pages Web spécifiques. Le contrôle de sécurité doit être effectué avant le chargement ou l’appel du contrôleur HTML ou de l’un des contrôleurs correspondants. Si la vérification échoue, la page peut être transférée ailleurs sans aucun effet secondaire des autres contrôleurs.
J'ai essayé les autres approches suggérées. Chacun a son propre ensemble de problèmes:
Utiliser OnEnter:
Utilisation de $ rootScope. $ On ('$ stateChangeStart'):
Ma solution consiste à utiliser une fonction de résolution pour définir une promesse qui obligera les contrôleurs de vue à attendre que la requête différée soit terminée avant d'être appelée. Cela fonctionne parfaitement pour empêcher le contrôleur de démarrer de manière asynchrone.
Voici un aperçu du code que j'ai utilisé:
.config(['$stateProvider', function ($stateProvider) {
// Handler for Restricting Access to a page using the state.resolve call
var accessRestrictionHandler = function($q, $rootScope, $state) {
var deferred = $q.defer();
// make sure user is logged in
asyncCheckForLogin(function(status) {
if (status != "Logged In") {
// You may save target page URL in cookie for use after login successful later
// To get the relative target URL, it is equal to ("#" + this.url).
// The "this" here is the current scope for the parent state structure of the resolve call.
$state.go("loginPage");
}
else // if logged in, continue to load the controllers. Controllers should not start till resolve() is called.
deferred.resolve();
}.bind(this));
return deferred.promise;
};
$stateProvider
.state('userProfile', {
url: '/userProfile',
views: {
'main': {
templateUrl: 'userProfile.html',
controller: 'userProfileCtrl'
}
},
// SIMPLY add the line below to all states that you want to secure
resolve: { loginRequired : accessRestrictionHandler }
})
.state(.... some other state)
.state(.... some other state);
}]);
J'espère que cela aidera certains d'entre vous.
Une autre approche consisterait à faire en sorte qu'un service/contrôleur écoute l'événement "$ stateChangeStart". Là, vous pouvez vérifier si l’état appelé a besoin d’une authentification et rediriger la demande. Voici un extrait:
$rootScope.$on('$stateChangeStart', function (event, nextState, currentState) {
if (!isAuthenticated(nextState)) {
console.debug('Could not change route! Not authenticated!');
$rootScope.$broadcast('$stateChangeError');
event.preventDefault();
$state.go('login');
}
});
isAuthenticated
pourrait mettre l'appel à vos services en attente, vérifier nextState.data
pour les propriétés liées à l'authentification, etc.
Une réponse tardive mais bon je préfère l'écrire quand même. Je préfère ne pas toucher le $ rootScope dans la mesure du possible. Voici le code sur lequel je travaille actuellement qui résume une autre solution à votre question:
state('dash', {
url:'/',
views:{
"topNav":{
templateUrl:"user/dash/partials/top-nav.html",
controller:'logoutCtrl',
},
"sideNav":{
templateUrl:"user/dash/partials/side-nav.html"
},
"body":{
templateUrl:"user/dash/partials/body.html",
controller:'testCtrl'
}
},
onEnter: function(Auth, $state){
if(!AuthSvc.isAuthenticated){
$state.go('login');
}
}
})
J'utilise JWT pour stocker les jetons sur le stockage local en utilisant ngStorage, qui fournit un service $ localStorage que j'injecte dans l'usine Auth que j'ai injectée onEnter