2015-12-31 7 views
15

Mit Angular2 zum Erstellen einer einzelnen Seite App, ich abfangen nicht authentifizierten Benutzerzugriff auf nicht-öffentlichen Routen in einem benutzerdefinierten RouterOutlet und umleiten sie in eine Login-Ansicht. Nach einer erfolgreichen Anmeldung möchte ich den Benutzer zu seiner ursprünglich angeforderten Ansicht und nicht zur Standardansicht umleiten.Verwenden von Angular2, Umleiten an die vorherige URL vor dem Login Umleitung

Ich habe festgestellt, dass Router eine renavigate() Funktion hat, die zur letzten erfolgreichen Route navigiert, aber die letzte erfolgreiche Route war /auth/login und nicht die ursprünglich angeforderte URL.

Grundsätzlich gilt: Wie kann ich auf, oder bestimmen die zuvor angeforderte URL?

Ich will nicht wirklich Abfrage-String-Parameter, das um greifen, es sei denn, ich muss wirklich. Idealerweise wäre es schön, Zugang zur history Sammlung als Teil der Router Komponente zu haben, ähnlich wie backbone.history!

+0

Was ist mit 'location.back()'? –

Antwort

16
  1. Verwenden Auth Guards (implementiert CanActivate) nicht authentifizierte Benutzer zu verhindern. Siehe official documentation mit Beispielen und this blog.
  2. Verwenden RouterStateSnapshot in der Auth-Wache die angeforderte URL zu erfassen.

    canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) 
    { 
        // keep the attempted URL for redirecting 
        this._loginService.redirectUrl = state.url; 
    } 
    
  3. zu dieser URL Umleiten auf eine erfolgreiche Authentifizierung mit Router (z.B. im login.component.ts). Z.B. this._router.navigateByUrl(redirectUrl);

P.S. Vorschläge von @MichaelOryl und @Vitali würden funktionieren, aber mein Weg ist mehr auf die endgültige Version von Angular2 ausgerichtet.

+1

Beachten Sie, dass 'state.url' nicht die gesamte URL enthält, die der Benutzer eingegeben hat - sie enthält die URL, die auf den überwachten Status verweist. Also (1) wird diese Methode nicht zu Kindern des bewachten Zustandes umleiten und (2) irgendwelche Hilfsrouten werden von der URL entfernt. – Isaac

+0

@ JonathanMiles Die Erklärung scheint ziemlich aufrecht zu sein, aber ich habe Angst, dass ich nicht folge. Ich verstehe nicht, wie man '_loginServie' erstellt. –

+1

@AaronC, die Schaffung eines Login-Service ist nicht in Frage. Nur um Sie in die richtige Richtung zu weisen, sehen Sie das [offizielle Tutorial zu Services] (https://angular.io/docs/ts/latest/tutorial/toh-pt4.html) und einige Beispiele: [from Auth0] (https://auth0.com/blog/angular-2-authentication/) und [von Jason Watmore] (http://jasonwatmore.com/post/2016/09/29/angular-2-user-registration-and -login-beispiel-tutorial) –

6

Vielleicht finden Sie, was Sie in der docs für die Location Klasse benötigen. Die back() Funktion könnte es möglicherweise für Sie tun.

Ein anderer Ansatz wäre, stattdessen die popstate Ereignisse in Location zu abonnieren. MDN has docs sprechen über die Werte, die Sie erhalten könnten.

class MyCLass { 
    constructor(private location: Location) { 
    location.subscribe((val) => { 
     // do something with the state that's passed in 
    }) 
    } 
} 

Andernfalls möchten Sie möglicherweise einen Dienst, der die Änderungen im Router verfolgt, damit Sie darauf zugreifen können.

class MyTrackingService { 
    constructor(private router: Router) { 
    router.subscribe((val) => { 
     // store the routes here so that you can peel them off as needed? 
    }) 
    } 
} 

In diesem Fall bin ich Zugriff auf das Router Objekt und auf Änderungen der abonnieren möchte, damit ich sie verfolgen konnte.

+0

Vielen Dank für Ihre Antwort, es ist eine Option zu prüfen. Idealerweise suche ich nach der Best Practice von Angular2, obwohl ich auch schätze, dass es immer noch BETA ist und sich wahrscheinlich ändern wird. Ich habe festgestellt, dass Location> PlatformLocation eine History-Sammlung enthält, aber es scheint keine gültige Methode für die Interaktion mit dem Router zu geben. Welches ist meine bevorzugte Methode und Angular2 empfohlene Methode zum Navigieren der App. –

4

Das ist für mich gearbeitet. Injizieren Sie es in den Konstruktor Ihrer Haupt-App-Komponente, nachdem Sie es in der Bootstrap-Methode registriert haben. Die erste val beim Laden der Seite sollte die ursprüngliche URL sein. Ich kündige mich gleich danach aus, um effizient zu sein, da ich (vielleicht noch) keine nachfolgenden Router-Ereignisse in diesem Dienst hören möchte. Injizieren Sie den Dienst an anderen Orten, an denen originalUrl benötigt wird.

import { Injectable } from '@angular/core'; 
import { Router } from '@angular/router'; 
import { Subscription } from 'rxjs/Subscription'; 

@Injectable() 
export class UrlTrackingService { 

    public originalUrl: string; 

    constructor(
    private router: Router 
) { 
    let subscription: Subscription = this.router.events.subscribe((val) => { 
     this.originalUrl = val.url; 
     subscription.unsubscribe(); 
    }); 
    } 

} 
+0

Können Sie bitte zeigen, wie Sie diese Komponente verwenden? – Pradeep

+0

Fügen Sie diesen Dienst in Ihrer 'Bootstrap'-Methode hinzu, damit Sie ihn in anderen Komponenten oder Diensten verwenden können. 'Bootstrap (AppComponent, [..., OriginalUrlService, ...]). Catch (err => console.error (err)); ' Dann injizieren Sie diesen Dienst wie jeden anderen Dienst (z. B. http) und verwenden Sie die Eigenschaft 'originalUrl', um die Routerumleitung nach Bedarf auszuführen. In Ihrer eigenen Komponente oder Dienst hinzuzufügen: ' Konstruktor ( private ous: OriginalUrlService, private Router: Router ) {...} privat irgendeinemethode(): void { this.router.navigateByUrl (this.ous. OriginalUrl); } ' –

3

aktualisiert Beispiel Angular 2.2 Verwendung.1

Auth-Schutz, die Original-URL geht einzuloggen Komponente:

import { Injectable } from '@angular/core'; 
import { Router, CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router'; 

@Injectable() 
export class AuthGuard implements CanActivate { 

    constructor(private router: Router) { } 

    canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) { 
     if (localStorage.getItem('currentUser')) { 
      // logged in so return true 
      return true; 
     } 

     // not logged in so redirect to login page with the return url 
     this.router.navigate(['/login', { returnUrl: state.url }]); 
     return false; 
    } 
} 

import { Component, OnInit } from '@angular/core'; 
import { Router, ActivatedRoute } from '@angular/router'; 

import { AlertService, AuthenticationService } from '../_services/index'; 

@Component({ 
    moduleId: module.id, 
    templateUrl: 'login.component.html' 
}) 

Anmeldung Komponente, die nach der Anmeldung zum vorherigen/Original-URL umleitet:

export class LoginComponent implements OnInit { 
    model: any = {}; 
    loading = false; 
    returnUrl: string; 

    constructor(
     private route: ActivatedRoute, 
     private router: Router, 
     private authenticationService: AuthenticationService, 
     private alertService: AlertService) { } 

    ngOnInit() { 
     // reset login status 
     this.authenticationService.logout(); 

     // get return url from route parameters or default to '/' 
     this.returnUrl = this.route.snapshot.params['returnUrl'] || '/'; 
    } 

    login() { 
     this.loading = true; 
     this.authenticationService.login(this.model.username, this.model.password) 
      .subscribe(
       data => { 
        // login successful so redirect to return url 
        this.router.navigate([this.returnUrl]); 
       }, 
       error => { 
        // login failed so display error 
        this.alertService.error(error); 
        this.loading = false; 
       }); 
    } 
} 

Für weitere Details und Arbeits Demo Sie kann auschecken this post

Verwandte Themen