Ich bin neu in AngularJS und ein wenig verwirrt darüber, wie ich Angular- "UI-Router" im folgenden Szenario verwenden kann:
Ich erstelle eine Webanwendung, die aus zwei Abschnitten besteht. Der erste Abschnitt ist die Homepage mit ihren Anmelde- und Anmeldeansichten, und der zweite Abschnitt ist das Dashboard (nach erfolgreicher Anmeldung).
Ich habe eine index.html
für den Home-Bereich mit seiner eckigen App und ui-router
Konfiguration zum Behandeln /login
und /signup
Anzeigen erstellt, und es gibt eine weitere Datei dashboard.html
für den Dashboard-Abschnitt mit seiner App und ui-router
Konfiguration zum Behandeln vieler Unteransichten.
Jetzt habe ich den Dashboard-Abschnitt fertiggestellt und weiß nicht, wie ich die beiden Abschnitte mit ihren unterschiedlichen eckigen Apps kombinieren soll. Wie kann ich die Home-App anweisen, zur Dashboard-App umzuleiten?
quelle
Antworten:
Ich bin gerade dabei, eine schönere Demo zu erstellen und einige dieser Dienste in ein verwendbares Modul zu bereinigen, aber hier ist, was ich mir ausgedacht habe. Dies ist ein komplexer Prozess, um einige Einschränkungen zu umgehen. Sie müssen dies in mehrere Teile zerlegen.
Schauen Sie sich dieses Plunk an .
Zunächst benötigen Sie einen Dienst zum Speichern der Benutzeridentität. Ich nenne das
principal
. Es kann überprüft werden, ob der Benutzer angemeldet ist, und auf Anfrage kann ein Objekt aufgelöst werden, das die wesentlichen Informationen zur Identität des Benutzers darstellt. Dies kann alles sein, was Sie benötigen, aber das Wesentliche sind ein Anzeigename, ein Benutzername, möglicherweise eine E-Mail und die Rollen, zu denen ein Benutzer gehört (sofern dies für Ihre App gilt). Der Principal verfügt auch über Methoden zum Durchführen von Rollenprüfungen.Zweitens benötigen Sie einen Dienst, der den Status überprüft, zu dem der Benutzer wechseln möchte, sicherstellt, dass er angemeldet ist (falls erforderlich; nicht erforderlich für Anmeldung, Zurücksetzen des Kennworts usw.), und dann eine Rollenprüfung durchführt (falls Ihre App braucht das). Wenn sie nicht authentifiziert sind, senden Sie sie an die Anmeldeseite. Wenn sie authentifiziert sind, aber eine Rollenprüfung nicht bestehen, senden Sie sie an eine Seite, auf die der Zugriff verweigert wurde. Ich rufe diesen Service an
authorization
.Nun sind alle brauchen, ist in abgehört zu tun
ui-router
ist$stateChangeStart
. Auf diese Weise können Sie den aktuellen Status und den Status, in den sie wechseln möchten, überprüfen und Ihre Berechtigungsprüfung einfügen. Wenn dies fehlschlägt, können Sie den Routenübergang abbrechen oder zu einer anderen Route wechseln.Der schwierige Teil beim Verfolgen der Identität eines Benutzers besteht darin, ihn nachzuschlagen, wenn Sie sich bereits authentifiziert haben (z. B. wenn Sie die Seite nach einer vorherigen Sitzung besuchen und ein Authentifizierungstoken in einem Cookie gespeichert haben oder wenn Sie eine Seite hart aktualisiert haben oder von einem Link auf eine URL abgelegt). Aufgrund der Funktionsweise
ui-router
müssen Sie Ihre Identitätsauflösung einmal durchführen, bevor Ihre Authentifizierung überprüft wird. Sie können dies mit derresolve
Option in Ihrer Statuskonfiguration tun . Ich habe einen übergeordneten Status für die Site, von dem alle Status erben, wodurch der Principal aufgelöst werden muss, bevor etwas anderes passiert.Hier gibt es ein anderes Problem ... wird
resolve
nur einmal angerufen. Sobald Ihr Versprechen für die Identitätssuche erfüllt ist, wird der Auflösungsdelegierte nicht mehr ausgeführt. Daher müssen wir Ihre Authentifizierungsprüfungen an zwei Stellen durchführen: einmal gemäß Ihrem Identitätsversprechenresolve
, das das erste Mal,$stateChangeStart
wenn Ihre App geladen wird, auflöst , und einmal, wenn die Auflösung durchgeführt wurde, das jede Zeit abdeckt, in der Sie durch Staaten navigieren.OK, was haben wir bisher gemacht?
Was machen wir jetzt? Nun können Sie Ihre Staaten in Regionen organisieren , die in Zeichen benötigen. Sie können authentifiziert / autorisierte Benutzer erfordern durch Zugabe von
data
mitroles
diesen Staaten (oder ein Elternteil von ihnen, wenn Sie die Vererbung verwenden möchten). Hier beschränken wir eine Ressource auf Administratoren:Jetzt können Sie Status für Status steuern, welche Benutzer auf eine Route zugreifen können. Irgendwelche anderen Bedenken? Vielleicht nur einen Teil einer Ansicht variieren, je nachdem, ob sie angemeldet sind oder nicht? Kein Problem. Verwenden Sie die
principal.isAuthenticated()
oder sogarprincipal.isInRole()
eine der zahlreichen Möglichkeiten, eine Vorlage oder ein Element bedingt anzuzeigen.Spritzen Sie zuerst
principal
in einen Controller oder was auch immer und kleben Sie ihn an das Zielfernrohr, damit Sie ihn aus Ihrer Sicht problemlos verwenden können:Ein- oder Ausblenden eines Elements:
Usw. so weiter, so weiter. In Ihrer Beispiel-App hätten Sie jedenfalls einen Status für die Startseite, über den nicht authentifizierte Benutzer vorbeischauen könnten. Sie können Links zu den Anmelde- oder Anmeldezuständen haben oder diese Formulare in diese Seite integriert haben. Was immer dir passt.
Die Dashboard-Seiten können alle von einem Status erben, bei dem die Benutzer angemeldet sein und beispielsweise ein
User
Rollenmitglied sein müssen. Alle Autorisierungsmaterialien, die wir besprochen haben, würden von dort fließen.quelle
$location.path
stattdessen mit$state.go
.$scope.user
in Ihrerthen
Funktion zuweisen . Sie können weiterhinuser
auf Ihre Ansichten verweisen . Wenn es aufgelöst ist, wird die Ansicht aktualisiert.$q.when(angular.noop).then(function(){$state.go('myState')
alles wie erwartet. Wenn ich anrufe,$state.go
während ein anderer Zustandsübergang nicht abgeschlossen ist, funktioniert er nicht (ich denke, das ist der Grund, warum er nicht funktioniert).Die bisher veröffentlichten Lösungen sind meiner Meinung nach unnötig kompliziert. Es gibt einen einfacheren Weg. Das Dokumentation von
ui-router
sagt,$locationChangeSuccess
dass$urlRouter.sync()
Sie einen Statusübergang abhören und verwenden , um ihn zu überprüfen, anzuhalten oder fortzusetzen. Aber auch das funktioniert eigentlich nicht.Hier sind jedoch zwei einfache Alternativen. Wähle eins:
Lösung 1: Zuhören
$locationChangeSuccess
$locationChangeSuccess
Sie können dort eine Logik anhören und ausführen, sogar eine asynchrone Logik. Basierend auf dieser Logik können Sie die Funktion undefiniert zurückgeben lassen, wodurch der Statusübergang wie gewohnt fortgesetzt wird, oder Sie können dies tun$state.go('logInPage')
, wenn der Benutzer authentifiziert werden muss. Hier ist ein Beispiel:Beachten Sie, dass dies das Laden des Zielstatus nicht verhindert, jedoch zur Anmeldeseite umleitet, wenn der Benutzer nicht autorisiert ist. Das ist in Ordnung, da der Server sowieso wirklich geschützt ist.
Lösung 2: Verwenden des Status
resolve
In dieser Lösung verwenden Sie die
ui-router
Auflösungsfunktion .Sie lehnen das Versprechen grundsätzlich ab
resolve
wenn der Benutzer nicht authentifiziert ist, und leiten es dann auf die Anmeldeseite weiter.So geht's:
Im Gegensatz zur ersten Lösung verhindert diese Lösung tatsächlich das Laden des Zielstatus.
quelle
state A
. Sie klicken auf einen Link, zu dem Sie wechselnprotected state B
möchten, aber Sie möchten sie weiterleitenlogInPage
. Wenn dies nicht der Fall ist$timeout
,ui-router
werden einfach alle Statusübergänge angehalten, sodass der Benutzer feststecktstate A
. Das$timeout
erlaubtui-router
, zuerst den anfänglichen Übergang zu zu verhindern,protected state B
da die Auflösung abgelehnt wurde und danach umgeleitet wirdlogInPage
.authenticate
Funktion eigentlich?authenticate
Funktion wird als Parameter an übergebenui-router
. Sie müssen es nicht selbst nennen.ui-router
nennt es.$stateChangeStart
?Die einfachste Lösung besteht darin , die Statusänderung zu verwenden
$stateChangeStart
undevent.preventDefault()
abzubrechen, wenn der Benutzer nicht authentifiziert ist, und ihn in den Authentifizierungsstatus umzuleiten, der die Anmeldeseite ist.quelle
Ich denke du brauchst eine
service
, die den Authentifizierungsprozess (und seine Speicherung) handhabt.In diesem Dienst benötigen Sie einige grundlegende Methoden:
isAuthenticated()
login()
logout()
Dieser Service sollte in Ihre Controller jedes Moduls eingefügt werden:
service.isAuthenticated()
Methode). Wenn nicht, leiten Sie zu / login umservice.login()
Methode zu authentifizierenEin gutes und robustes Beispiel für dieses Verhalten ist die Projekt- Winkel-App und speziell das Sicherheitsmodul, das auf dem Fantastischen basiert HTTP Auth Interceptor-Modul
Hoffe das hilft
quelle
Ich habe dieses Modul erstellt, um diesen Prozess zum Kinderspiel zu machen
Sie können Dinge tun wie:
Oder auch
Es ist brandneu, aber einen Besuch wert!
https://github.com/Narzerus/angular-permission
quelle
Ich wollte eine andere Lösung mit dem UI-Router 1.0.0.X teilen
Wie Sie vielleicht wissen, sind stateChangeStart und stateChangeSuccess jetzt veraltet. https://github.com/angular-ui/ui-router/issues/2655
Stattdessen sollten Sie $ -Übergänge verwenden http://angular-ui.github.io/ui-router/1.0.0-alpha.1/interfaces/transition.ihookregistry.html
So habe ich es erreicht:
Zuerst habe ich und AuthService mit einigen nützlichen Funktionen
Dann habe ich diese Konfiguration:
Sie können sehen, dass ich benutze
um den Status zu markieren, auf den nur zugegriffen werden kann, wenn er authentifiziert ist.
dann benutze ich auf dem .run die Übergänge, um den authentifizierten Zustand zu überprüfen
Ich erstelle dieses Beispiel mit Code, der in der Dokumentation zu $ transitions enthalten ist. Ich bin ziemlich neu mit dem UI-Router, aber es funktioniert.
Hoffe es kann jedem helfen.
quelle
Hier ist, wie wir aus der Endlos-Routing-Schleife herausgekommen sind und immer noch
$state.go
statt verwendet haben$location.path
quelle
Ich habe eine andere Lösung: Diese Lösung funktioniert perfekt, wenn Sie nur Inhalte haben, die Sie anzeigen möchten, wenn Sie angemeldet sind. Definieren Sie eine Regel, bei der Sie überprüfen, ob Sie angemeldet sind und nicht den Pfad der Whitelist-Routen.
In meinem Beispiel frage ich, ob ich nicht angemeldet bin und die aktuelle Route, die ich routen möchte, nicht Teil von "/ login" ist, da meine Whitelist-Routen die folgenden sind
Ich habe also sofort Zugriff auf diese beiden Routen und jede andere Route wird überprüft, wenn Sie online sind.
Hier ist meine gesamte Routing-Datei für das Anmeldemodul
() => { /* code */ }
ist ES6-Syntax, verwenden Sie stattdessenfunction() { /* code */ }
quelle
Verwenden Sie $ http Interceptor
Mit einem $ http-Interceptor können Sie Header an das Back-End oder umgekehrt senden und Ihre Überprüfungen auf diese Weise durchführen.
Großartiger Artikel über $ http Interceptors
Beispiel:
Fügen Sie dies in Ihre .config- oder .run-Funktion ein.
quelle
Zunächst benötigen Sie einen Dienst, den Sie in Ihre Controller einfügen können und der eine Vorstellung vom Status der App-Authentifizierung hat. Das Fortbestehen von Authentifizierungsdetails mit lokalem Speicher ist eine gute Möglichkeit, sich dem anzunähern.
Als Nächstes müssen Sie den Status der Authentifizierung überprüfen, bevor sich der Status ändert. Da Ihre App einige Seiten enthält, die authentifiziert werden müssen, und andere, die dies nicht tun, erstellen Sie eine übergeordnete Route, die die Authentifizierung überprüft, und machen Sie alle anderen Seiten, für die dieselbe erforderlich ist, zu einem untergeordneten Element dieses übergeordneten Elements.
Schließlich müssen Sie feststellen, ob Ihr aktuell angemeldeter Benutzer bestimmte Vorgänge ausführen kann. Dies kann erreicht werden, indem Sie Ihrem Authentifizierungsdienst eine 'can'-Funktion hinzufügen. Can akzeptiert zwei Parameter: - Aktion - Erforderlich - (dh 'manage_dashboards' oder 'create_new_dashboard') - Objekt - optional - Objekt, an dem gearbeitet wird. Wenn Sie beispielsweise ein Dashboard-Objekt hatten, möchten Sie möglicherweise überprüfen, ob dashboard.ownerId === loggedInUser.id ist. (Natürlich sollten vom Client übergebene Informationen niemals vertrauenswürdig sein, und Sie sollten dies immer auf dem Server überprüfen, bevor Sie sie in Ihre Datenbank schreiben.)
** HAFTUNGSAUSSCHLUSS: Der obige Code ist Pseudocode und wird ohne Garantie geliefert **
quelle