Je suis nouveau sur AngularJS et je suis un peu confus quant à la façon dont je peux utiliser angular- "ui-router" dans le scénario suivant:
Je crée une application web qui se compose de deux sections. La première section est la page d'accueil avec ses vues de connexion et d'inscription, et la deuxième section est le tableau de bord (après une connexion réussie).
J'ai créé un index.html
pour la section d'accueil avec son application angulaire et sa ui-router
configuration à gérer /login
et ses /signup
vues, et il existe un autre fichier dashboard.html
pour la section du tableau de bord avec son application et sa ui-router
configuration pour gérer de nombreuses sous-vues.
Maintenant, j'ai terminé la section du tableau de bord et je ne sais pas comment combiner les deux sections avec leurs différentes applications angulaires. Comment puis-je dire à l'application domestique de se rediriger vers l'application de tableau de bord?
la source
Réponses:
Je suis en train de faire une démo plus agréable ainsi que de nettoyer certains de ces services en un module utilisable, mais voici ce que j'ai trouvé. Il s'agit d'un processus complexe pour contourner certaines mises en garde, alors accrochez-vous. Vous devrez le décomposer en plusieurs morceaux.
Jetez un oeil à ce plunk .
Tout d'abord, vous avez besoin d'un service pour stocker l'identité de l'utilisateur. J'appelle ça
principal
. Il peut être vérifié pour voir si l'utilisateur est connecté et, sur demande, il peut résoudre un objet qui représente les informations essentielles sur l'identité de l'utilisateur. Cela peut être tout ce dont vous avez besoin, mais l'essentiel serait un nom d'affichage, un nom d'utilisateur, éventuellement un e-mail et les rôles auxquels un utilisateur appartient (si cela s'applique à votre application). Le directeur dispose également de méthodes pour effectuer des vérifications de rôle.Deuxièmement, vous avez besoin d'un service qui vérifie l'état dans lequel l'utilisateur veut aller, s'assure qu'il est connecté (si nécessaire; pas nécessaire pour la connexion, la réinitialisation du mot de passe, etc.), puis effectue une vérification des rôles (si votre application en a besoin). S'ils ne sont pas authentifiés, envoyez-les sur la page de connexion. S'ils sont authentifiés, mais échouent à une vérification de rôle, envoyez-les vers une page d'accès refusé. J'appelle ce service
authorization
.Maintenant , tout ce que vous devez faire est d' écouter dans le
ui-router
« s$stateChangeStart
. Cela vous donne la possibilité d'examiner l'état actuel, l'état dans lequel ils veulent aller et d'insérer votre vérification d'autorisation. En cas d'échec, vous pouvez annuler la transition de l'itinéraire ou passer à un autre itinéraire.La partie délicate du suivi de l'identité d'un utilisateur consiste à la rechercher si vous vous êtes déjà authentifié (par exemple, vous visitez la page après une session précédente et avez enregistré un jeton d'authentification dans un cookie, ou vous avez peut-être actualisé une page, ou déposé sur une URL à partir d'un lien). En raison de la façon dont cela
ui-router
fonctionne, vous devez résoudre votre identité une fois, avant vos vérifications d'authentification. Vous pouvez le faire en utilisant l'resolve
option dans votre configuration d'état. J'ai un état parent pour le site dont tous les états héritent, ce qui oblige le principal à être résolu avant que quoi que ce soit d'autre se produise.Il y a un autre problème ici ...
resolve
n'est appelé qu'une seule fois. Une fois votre promesse de recherche d'identité terminée, elle ne réexécutera pas le délégué de résolution. Nous devons donc effectuer vos vérifications d'authentification à deux endroits: une fois conformément à votre promesse d'identité résolueresolve
, qui couvre la première fois que votre application se charge, et une fois$stateChangeStart
si la résolution a été effectuée, qui couvre chaque fois que vous naviguez dans les États.OK, qu'avons-nous fait jusqu'à présent?
Où allons-nous à partir d'ici? Eh bien, vous pouvez organiser vos états en régions qui nécessitent une connexion. Vous pouvez exiger des utilisateurs authentifiés / autorisés en ajoutant
data
avecroles
à ces états (ou un parent d'entre eux, si vous souhaitez utiliser l'héritage). Ici, nous limitons une ressource aux administrateurs:Vous pouvez désormais contrôler état par état quels utilisateurs peuvent accéder à un itinéraire. D'autres soucis? Peut-être varier seulement une partie d'une vue selon qu'ils sont connectés ou non? Aucun problème. Utilisez le
principal.isAuthenticated()
ou mêmeprincipal.isInRole()
avec l'une des nombreuses façons dont vous pouvez conditionnellement afficher un modèle ou un élément.Tout d'abord, injectez-le
principal
dans un contrôleur ou autre, et collez-le sur la portée afin de pouvoir l'utiliser facilement dans votre vue:Afficher ou masquer un élément:
Etc., etc., etc. Quoi qu'il en soit, dans votre exemple d'application, vous auriez un état pour la page d'accueil qui permettrait aux utilisateurs non authentifiés de passer. Ils peuvent avoir des liens vers les états de connexion ou d'inscription, ou avoir ces formulaires intégrés dans cette page. Tout ce qui vous convient.
Les pages du tableau de bord peuvent toutes hériter d'un état qui requiert que les utilisateurs soient connectés et, par exemple,
User
membres du rôle. Tous les éléments d'autorisation dont nous avons discuté en découleraient.la source
$location.path
place de$state.go
.$scope.user
votrethen
fonction. Vous pouvez toujours faire référenceuser
dans vos vues; une fois résolu, la vue sera mise à jour.$q.when(angular.noop).then(function(){$state.go('myState')
, tout fonctionne comme prévu. Si j'appelle$state.go
alors qu'une autre transition d'état n'est pas terminée, cela ne fonctionnera pas (je pense que c'est la raison pour laquelle cela ne fonctionnera pas).À mon avis, les solutions publiées jusqu'à présent sont inutilement compliquées. Il existe un moyen plus simple. La documentation de
ui-router
dit écouter$locationChangeSuccess
et utiliser$urlRouter.sync()
pour vérifier une transition d'état, l'arrêter ou la reprendre. Mais même cela ne fonctionne pas.Cependant, voici deux alternatives simples. Choisissez-en un:
Solution 1: écouter
$locationChangeSuccess
Vous pouvez écouter
$locationChangeSuccess
et exécuter une logique, même une logique asynchrone. Sur la base de cette logique, vous pouvez laisser la fonction retourner indéfinie, ce qui entraînera la transition d'état à continuer normalement, ou vous pouvez le faire$state.go('logInPage')
, si l'utilisateur doit être authentifié. Voici un exemple:Gardez à l'esprit que cela n'empêche pas réellement l'état cible de se charger, mais il redirige vers la page de connexion si l'utilisateur n'est pas autorisé. Ce n'est pas grave car la vraie protection est sur le serveur, de toute façon.
Solution 2: utilisation de l'état
resolve
Dans cette solution, vous utilisez la
ui-router
fonction de résolution .Vous rejetez essentiellement la promesse
resolve
si l'utilisateur n'est pas authentifié, puis vous les redirigez vers la page de connexion.Voici comment ça se passe:
Contrairement à la première solution, cette solution empêche le chargement de l'état cible.
la source
state A
. Ils cliquent sur un lien pour y accéder,protected state B
mais vous souhaitez les rediriger verslogInPage
. S'il n'y a pas$timeout
,ui-router
arrêtera simplement toutes les transitions d'état, de sorte que l'utilisateur serait coincéstate A
. Le$timeout
permetui-router
d'abord d'empêcher la transition initiale versprotected state B
car la résolution a été rejetée et après cela, il redirige verslogInPage
.authenticate
fonction est-elle réellement appelée?authenticate
fonction @Imray est passée en paramètre àui-router
. Vous n'avez pas à l'appeler vous-même.ui-router
l'appelle.$stateChangeStart
?La solution la plus simple consiste à utiliser
$stateChangeStart
etevent.preventDefault()
à annuler le changement d'état lorsque l'utilisateur n'est pas authentifié et à le rediriger vers l' état d' authentification qui est la page de connexion.la source
Je pense que vous avez besoin d'un
service
qui gère le processus d'authentification (et son stockage).Dans ce service, vous aurez besoin de quelques méthodes de base:
isAuthenticated()
login()
logout()
Ce service doit être injecté dans vos contrôleurs de chaque module:
service.isAuthenticated()
méthode). sinon, redirigez vers / loginservice.login()
méthodeUn bon et robuste exemple de ce comportement est le projet angular-app et en particulier son module de sécurité qui est basé sur le génial module HTTP Auth Interceptor
J'espère que cela t'aides
la source
J'ai créé ce module pour aider à faire de ce processus un morceau de gâteau
Vous pouvez faire des choses comme:
Ou aussi
Il est tout neuf mais mérite d'être vérifié!
https://github.com/Narzerus/angular-permission
la source
Je voulais partager une autre solution fonctionnant avec le routeur ui 1.0.0.X
Comme vous le savez peut-être, stateChangeStart et stateChangeSuccess sont désormais obsolètes. https://github.com/angular-ui/ui-router/issues/2655
À la place, vous devez utiliser $ transitions http://angular-ui.github.io/ui-router/1.0.0-alpha.1/interfaces/transition.ihookregistry.html
Voici comment je l'ai réalisé:
J'ai d'abord et AuthService avec quelques fonctions utiles
Ensuite, j'ai cette configuration:
Vous pouvez voir que j'utilise
pour marquer l'état uniquement accessible s'il est authentifié.
puis, sur le .run, j'utilise les transitions pour vérifier l'état d'authentification
Je construis cet exemple en utilisant du code trouvé dans la documentation de $ transitions. Je suis assez nouveau avec le routeur ui mais ça marche.
J'espère que cela peut aider n'importe qui.
la source
Voici comment nous sommes sortis de la boucle de routage infinie et toujours utilisés
$state.go
au lieu de$location.path
la source
J'ai une autre solution: cette solution fonctionne parfaitement lorsque vous n'avez que du contenu que vous souhaitez afficher lorsque vous êtes connecté. Définissez une règle dans laquelle vous vérifiez si vous êtes connecté et ce n'est pas le chemin des routes de la liste blanche.
Dans mon exemple, je demande si je ne suis pas connecté et que l'itinéraire actuel que je souhaite router ne fait pas partie de `/ login ', car mes itinéraires sur liste blanche sont les suivants
J'ai donc un accès instantané à ces deux itinéraires et tous les autres itinéraires seront vérifiés si vous êtes en ligne.
Voici tout mon fichier de routage pour le module de connexion
() => { /* code */ }
est la syntaxe ES6, utilisez plutôtfunction() { /* code */ }
la source
Utiliser $ http Interceptor
En utilisant un intercepteur $ http, vous pouvez envoyer des en-têtes à Back-end ou l'inverse et faire vos vérifications de cette façon.
Excellent article sur les intercepteurs $ http
Exemple:
Mettez ceci dans votre fonction .config ou .run.
la source
Vous aurez d'abord besoin d'un service que vous pouvez injecter dans vos contrôleurs qui a une idée de l'état d'authentification de l'application. La persistance des détails d'authentification avec le stockage local est une manière décente de l'aborder.
Ensuite, vous devrez vérifier l'état d'authentification juste avant les changements d'état. Étant donné que votre application possède certaines pages qui doivent être authentifiées et d'autres qui ne le font pas, créez un itinéraire parent qui vérifie l'authentification et faites en sorte que toutes les autres pages qui nécessitent la même chose soient des enfants de ce parent.
Enfin, vous aurez besoin d'un moyen de savoir si votre utilisateur actuellement connecté peut effectuer certaines opérations. Ceci peut être réalisé en ajoutant une fonction «can» à votre service d'authentification. Peut prendre deux paramètres: - action - obligatoire - (c'est-à-dire 'manage_dashboards' ou 'create_new_dashboard') - objet - facultatif - objet en cours d'opération. Par exemple, si vous aviez un objet de tableau de bord, vous souhaiterez peut-être vérifier si dashboard.ownerId === connectedInUser.id. (Bien sûr, les informations transmises par le client ne doivent jamais être approuvées et vous devez toujours les vérifier sur le serveur avant de les écrire dans votre base de données).
** AVERTISSEMENT: Le code ci-dessus est un pseudo-code et est livré sans aucune garantie **
la source