2015-12-31 3 views
15

Использование Angular2 для создания одностраничного приложения, я перехватываю неавторизованный доступ пользователей к непубличным маршрутам в пользовательском RouterOutlet и перенаправляет их в режим входа. После успешного входа в систему я хочу перенаправить пользователя в свое первоначально запрошенное представление, а не по умолчанию.Использование Angular2, как перенаправить на предыдущий URL-адрес до переадресации входа

Я заметил, что Router имеет renavigate() функцию, которая переходит к последней успешной маршрута, но последний успешный маршрут был /auth/login и не первоначально заявленное URL.

В принципе: Как я могу получить доступ или определить ранее запрошенный URL?

Я действительно не хочу прибегать к передаче параметров строки запроса, если только мне это не нужно. В идеале было бы неплохо иметь доступ к коллекции history как часть компонента Router, похожее на backbone.history!

+0

Как насчет 'location.back()'? –

ответ

16
  1. Использование аутентификации Guards (орудия CanActivate) для предотвращения неаутентифицированных пользователей. См. official documentation с примерами и this blog.
  2. Используйте RouterStateSnapshot в защитнике, чтобы захватить запрошенный URL.

    canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) 
    { 
        // keep the attempted URL for redirecting 
        this._loginService.redirectUrl = state.url; 
    } 
    
  3. Перенаправление к этому URL на успешной аутентификации с использованием Router (например, в login.component.ts). Например. this._router.navigateByUrl(redirectUrl);

P.S. Предложения @MichaelOryl и @Vitali будут работать, но мой путь более согласован с окончательным выпуском Angular2.

+1

Обратите внимание, что' state.url' фактически не содержит весь URL-адрес, который вводил пользователь, - он содержит URL-адрес, указывающий на охраняемое состояние. Итак, (1) этот метод не будет перенаправлять детям охраняемого состояния и (2) любые вспомогательные маршруты будут удалены из URL-адреса. – Isaac

+0

@JonathanMiles Объяснение кажется довольно напряженным вперед, но я боюсь, что не следую. Я не понимаю, как создать '_loginServie'. –

+1

@AaronC, создавая службу входа в систему, выходит за рамки вопроса. Чтобы указать на правильное направление, см. [Официальный учебник по услугам] (https://angular.io/docs/ts/latest/tutorial/toh-pt4.html) и несколько примеров: [из Auth0] (https://auth0.com/blog/angular-2-authentication/) и [от Джейсона Уотмора] (http://jasonwatmore.com/post/2016/09/29/angular-2-user-registration-and -login-пример-учебник) –

6

Вы можете найти то, что вам нужно в docs для класса Location. Функция back() может сделать это за вас.

Другим подходом было бы подписаться на события popstate в Location. MDN has docs говорить о значениях, которые вы ожидаете получить.

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

В противном случае может потребоваться служба, которая отслеживает изменения в маршрутизаторе, чтобы вы могли получить к ним доступ.

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

В этом случае я получить доступ к Router объект и подписываться на любые изменения, чтобы я мог отслеживать их.

+0

Спасибо за ваш ответ, это один из вариантов рассмотрения. В идеале я ищу лучшую методику Angular2, хотя я также ценю, что она все еще BETA и, вероятно, изменится. Я заметил, что Location> PlatformLocation содержит коллекцию истории, но, похоже, нет действительного метода взаимодействия с ним с маршрутизатором; который является моим предпочтительным методом и рекомендованным методом Angular2 навигации по приложению. –

4

Это сработало для меня. Внесите его в свой конструктор компонента основного приложения, зарегистрировав его в методе начальной загрузки. Первым val на загрузку страницы должен быть исходный URL. Я отказываюсь от подписки сразу после того, чтобы быть эффективным, так как я не (возможно, еще) хочу слушать последующие события маршрутизатора в этой службе. Внесите сервис в другие места, где требуется оригиналUrl.

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

Не могли бы вы показать, как использовать этот компонент? – Pradeep

+0

В вашем методе 'bootstrap' добавьте эту услугу, чтобы вы могли использовать ее в других компонентах или службах. 'bootstrap (AppComponent, [..., OriginalUrlService, ...]). Catch (err => console.error (err)); ' Затем введите эту службу так же, как и любую другую услугу (например, http), и используйте свойство' originalUrl' для выполнения перенаправления маршрутизатора по мере необходимости. В вашем собственном компоненте или услуге добавить: ' конструктора ( частного Ous: OriginalUrlService, частного маршрутизатор: маршрутизатор ) {...} личного SomeMethod(): недействительный { this.router.navigateByUrl (this.ous. originalUrl); } ' –

3

Обновленный пример использования углового 2.2.1

Auth Guard, который проходит оригинальный URL для входа в систему компонент:

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

Войти Компонент, который перенаправляет к предыдущему/первоначальному URL после входа в систему:

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

Для получения более подробной информации и рабочей Демонстрационный можно проверить this post