Ich komme aus der Asp.Net MVC-Welt, in der Benutzer, die versuchen, auf eine nicht autorisierte Seite zuzugreifen, automatisch auf die Anmeldeseite umgeleitet werden.
Ich versuche, dieses Verhalten auf Angular zu reproduzieren. Ich bin auf den @ CanActivate-Dekorator gestoßen, aber dies führt dazu, dass die Komponente überhaupt nicht gerendert wird und keine Umleitung erfolgt.
Meine Frage lautet wie folgt:
- Bietet Angular eine Möglichkeit, dieses Verhalten zu erreichen?
- Wenn das so ist, wie? Ist es eine gute Praxis?
- Wenn nicht, was wäre die beste Vorgehensweise für den Umgang mit der Benutzerautorisierung in Angular?
login
typescript
angular
angular2-routing
Amaury
quelle
quelle
Antworten:
Update: Ich habe ein vollständiges Skelett- Angular 2-Projekt mit OAuth2-Integration auf Github veröffentlicht, das die unten genannte Direktive in Aktion zeigt.
Ein Weg, dies zu tun, wäre die Verwendung von a
directive
. Im Gegensatz zu Angular 2components
, bei dem es sich im Grunde genommen um neue HTML-Tags (mit zugehörigem Code) handelt, die Sie in Ihre Seite einfügen, ist eine attributive Direktive ein Attribut, das Sie in ein Tag einfügen, wodurch ein gewisses Verhalten auftritt. Docs hier .Das Vorhandensein Ihres benutzerdefinierten Attributs führt dazu, dass Dinge mit der Komponente (oder dem HTML-Element) geschehen, in die Sie die Direktive eingefügt haben. Beachten Sie diese Direktive, die ich für meine aktuelle Angular2 / OAuth2-Anwendung verwende:
Hierbei wird ein von mir geschriebener Authentifizierungsdienst verwendet, um festzustellen, ob der Benutzer bereits angemeldet ist, und um das Authentifizierungsereignis zu abonnieren , damit ein Benutzer ausgeschlossen werden kann, wenn er sich abmeldet oder eine Zeitüberschreitung aufweist.
Sie könnten das Gleiche tun. Sie würden eine Anweisung wie meine erstellen, die prüft, ob ein erforderliches Cookie oder andere Statusinformationen vorhanden sind, die darauf hinweisen, dass der Benutzer authentifiziert ist. Wenn sie nicht die Flags haben, nach denen Sie suchen, leiten Sie den Benutzer auf Ihre öffentliche Hauptseite (wie ich) oder Ihren OAuth2-Server (oder was auch immer) weiter. Sie würden dieses Direktivenattribut auf jede Komponente setzen, die geschützt werden muss. In diesem Fall könnte es
protected
wie in der oben eingefügten Direktive aufgerufen werden .Anschließend möchten Sie den Benutzer zu einer Anmeldeansicht in Ihrer App navigieren / umleiten und dort die Authentifizierung durchführen. Sie müssten die aktuelle Route auf die Route ändern, für die Sie dies tun möchten. In diesem Fall würden Sie die Abhängigkeitsinjektion verwenden, um ein Router-Objekt in der
constructor()
Funktion Ihrer Direktive abzurufen, und dann dienavigate()
Methode verwenden, um den Benutzer an Ihre Anmeldeseite zu senden (wie in meinem obigen Beispiel).Dies setzt voraus, dass Sie irgendwo eine Reihe von Routen haben, die ein
<router-outlet>
Tag steuern , das ungefähr so aussieht:Wenn Sie stattdessen den Benutzer zu einer externen URL wie Ihrem OAuth2-Server umleiten müssten, müsste Ihre Direktive Folgendes tun:
quelle
Hier ist ein aktualisiertes Beispiel mit Angular 4 (auch kompatibel mit Angular 5 - 8).
Routen mit durch AuthGuard geschützter Heimroute
AuthGuard leitet zur Anmeldeseite weiter, wenn der Benutzer nicht angemeldet ist
Aktualisiert, um die ursprüngliche URL in den Abfrageparametern an die Anmeldeseite zu übergeben
Das vollständige Beispiel und die funktionierende Demo finden Sie in diesem Beitrag
quelle
currentUser
inlocalStorage
festlegen. z.B.localStorage.setItem('currentUser', 'dddddd')
?Verwendung mit dem endgültigen Router
Mit der Einführung des neuen Routers wurde es einfacher, die Routen zu bewachen. Sie müssen eine Wache definieren, die als Dienst fungiert, und sie der Route hinzufügen.
Übergeben Sie nun das
LoggedInGuard
an die Route und fügen Sie es auch demproviders
Array des Moduls hinzu.Die Moduldeklaration:
Ausführlicher Blog-Beitrag zur Funktionsweise der endgültigen Version: https://medium.com/@blacksonic86/angular-2-authentication-revisited-611bf7373bf9
Verwendung mit dem veralteten Router
Eine robustere Lösung besteht darin, die
RouterOutlet
und beim Aktivieren einer Routenprüfung zu erweitern, ob der Benutzer angemeldet ist. Auf diese Weise müssen Sie Ihre Direktive nicht in jede Komponente kopieren und einfügen. Außerdem kann eine Umleitung basierend auf einer Unterkomponente irreführend sein.Das
UserService
steht für den Ort, an dem sich Ihre Geschäftslogik befindet, unabhängig davon, ob der Benutzer angemeldet ist oder nicht. Sie können es einfach mit DI im Konstruktor hinzufügen.Wenn der Benutzer zu einer neuen URL auf Ihrer Website navigiert, wird die Aktivierungsmethode mit der aktuellen Anweisung aufgerufen. Daraus können Sie die URL abrufen und entscheiden, ob sie zulässig ist oder nicht. Wenn nicht, leiten Sie einfach zur Anmeldeseite weiter.
Eine letzte Sache, die noch funktioniert, ist, sie an unsere Hauptkomponente anstatt an die eingebaute zu übergeben.
Diese Lösung kann nicht mit dem
@CanActive
Lifecycle Decorator verwendet werden, da die Aktivierungsmethode vonRouterOutlet
nicht aufgerufen wird , wenn die an sie übergebene Funktion false auflöst .Schrieb auch einen ausführlichen Blog-Beitrag darüber: https://medium.com/@blacksonic86/authentication-in-angular-2-958052c64492
quelle
Failed to lint <classname>.router-outlet.ts[15,28]. In the constructor of class "LoggedInRouterOutlet", the parameter "nameAttr" uses the @Attribute decorator, which is considered as a bad practice. Please, consider construction of type "@Input() nameAttr: string".
konnte nicht herausfinden, was im Konstruktor ("_parentRounter") geändert werden muss, um diese Nachricht zu entfernen. Irgendwelche Gedanken?_parentRouter: Router, @Input() nameAttr: string,
Ändern der Zeile in und tslint löst den Fehler nicht mehr aus. Ersetzte auch den Import "Attribut" in "Eingabe" vom Winkelkern. Hoffe das hilft.Bitte Router Outlet nicht überschreiben! Es ist ein Albtraum mit der neuesten Router-Version (3.0 Beta).
Verwenden Sie stattdessen die Schnittstellen CanActivate und CanDeactivate und legen Sie die Klasse in Ihrer Routendefinition als canActivate / canDeactivate fest.
So wie das:
Klasse:
Siehe auch: https://angular.io/docs/ts/latest/guide/router.html#!#can-activate-guard
quelle
Nach den fantastischen Antworten oben möchte ich auch
CanActivateChild
: Kinderrouten bewachen. Es kann verwendet werden, umguard
untergeordneten Routen hinzuzufügen , die für Fälle wie ACLs hilfreich sindEs geht so
Dies ist https://angular.io/docs/ts/latest/guide/router.html#!#can-activate-guard entnommen
quelle
Verweisen Sie auf diesen Code, auth.ts-Datei
quelle
1. Create a guard as seen below. 2. Install ngx-cookie-service to get cookies returned by external SSO. 3. Create ssoPath in environment.ts (SSO Login redirection). 4. Get the state.url and use encodeURIComponent.
quelle