2015-12-31 8 views
15

Utilizzando Angular2 per creare un'applicazione singola, sto intercettando l'accesso utente non autenticato a percorsi non pubblici in un RouterOutlet personalizzato e reindirizzandoli a una vista di accesso. Dopo aver effettuato correttamente il login, desidero reindirizzare l'utente alla vista originariamente richiesta, piuttosto che alla vista predefinita.Utilizzo di Angular2, come reindirizzare all'url precedente prima del reindirizzamento dell'accesso

ho notato che Router ha una funzione renavigate() che naviga verso l'ultimo percorso di successo, ma l'ultimo percorso di successo era /auth/login e non l'URL originariamente richiesto.

Fondamentalmente: come posso accedere o determinare l'url precedentemente richiesto?

Non voglio davvero ricorrere ai parametri di stringa di query in giro, a meno che non sia necessario. Idealmente sarebbe bello avere accesso alla collezione history come parte del componente Router, simile a backbone.history!

+0

Che dire di 'location.back()'? –

risposta

16
  1. Utilizzare Auth Guardie (attrezzi CanActivate) per impedire agli utenti non autenticati. Vedi official documentation con esempi e this blog.
  2. Utilizzare l'autenticazione RouterStateSnapshot nella protezione per acquisire l'URL richiesto.

    canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) 
    { 
        // keep the attempted URL for redirecting 
        this._loginService.redirectUrl = state.url; 
    } 
    
  3. reindirizzare a tale URL autenticazione di successo con l'utilizzo di Router (ad esempio nel login.component.ts). Per esempio. this._router.navigateByUrl(redirectUrl);

P.S. I suggerimenti di @MichaelOryl e @Vitali funzionerebbero, ma la mia strada è più allineata con la versione finale di Angular2.

+1

Si noti che' state.url' in realtà non contiene l'intero url che l'utente ha inserito, contiene l'url che punta allo stato protetto. Quindi (1) questo metodo non reindirizzerà ai bambini dello stato protetto e (2) eventuali percorsi ausiliari verranno rimossi dall'URL. – Isaac

+0

@ JonathanMiles La spiegazione sembra piuttosto veloce, ma temo di non seguirmi. Non capisco come creare il '_loginServie'. –

+1

@AaronC, la creazione di un servizio di accesso è fuori dall'ambito della domanda. Solo per indicarti la giusta direzione, consulta il [tutorial ufficiale sui servizi] (https://angular.io/docs/ts/latest/tutorial/toh-pt4.html) e un paio di esempi: [da Auth0] (https://auth0.com/blog/angular-2-authentication/) e [di Jason Watmore] (http://jasonwatmore.com/post/2016/09/29/angular-2-user-registration-and -login-example-tutorial) –

6

È possibile trovare ciò che è necessario nello docs per la classe Location. La funzione back() potrebbe farlo per te.

Un altro approccio sarebbe quello di iscriversi agli eventi popstate in Location, invece. MDN has docs parlando dei valori che potresti aspettarti di ricevere.

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

Altrimenti si potrebbe desiderare un servizio che tenga traccia delle modifiche nel router in modo che sia possibile accedervi.

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

In questo caso sto accesso all'oggetto Router e la sottoscrizione di eventuali modifiche in modo che io potessi tenere traccia.

+0

Grazie per la risposta, è un'opzione da considerare. Idealmente sto cercando le migliori pratiche di Angular2, anche se apprezzo anche che è ancora BETA e che probabilmente cambierà. Ho notato che Location> PlatformLocation contiene una raccolta di cronologia ma sembra che non ci sia un metodo valido per interagire con esso dal Router; che è il mio metodo preferito e il metodo consigliato da Angular2 per navigare nell'app. –

4

Questo ha funzionato per me. Inseriscilo nel costruttore del componente principale dell'app che lo ha registrato nel metodo bootstrap. Il primo val sul caricamento della pagina deve essere l'URL originale. Sto annullando l'iscrizione subito dopo essere efficiente poiché non desidero (forse ancora) ascoltare i successivi eventi del router in questo servizio. Inietta il servizio in altri posti in cui è necessario originalUrl.

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

Puoi mostrare come usare questo componente? – Pradeep

+0

Nel metodo 'bootstrap' aggiungi questo servizio, così puoi usarlo in altri componenti o servizi. 'bootstrap (AppComponent, [..., OriginalUrlService, ...]). Catch (err => console.error (err)); ' Quindi iniettare questo servizio come qualsiasi altro servizio (ad esempio http) e utilizzare la proprietà' originalUrl' per eseguire il reindirizzamento del router, se necessario. In un componente personalizzato o servizio aggiungere: ' costruttore ( UO privato: OriginalUrlService, router privato: Router ) {...} someMethod privato(): void { this.router.navigateByUrl (this.ous. originalUrl); } ' –

3

Esempio aggiornato con Angular 2.2.1

Auth guardia che passa URL originale per il login componente:

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' 
}) 

Accesso componente che reindirizza al precedente URL/originale dopo login:

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; 
       }); 
    } 
} 

Per maggiori dettagli e si demo funzionante può controllare this post

Problemi correlati