使用 Angular2,如何在登录重定向之前重定向到上一个 url

Using Angular2, how to redirect to previous url before login redirect

使用 Angular2 创建单页应用程序,我在自定义 RouterOutlet 中拦截未经身份验证的用户对非 public 路由的访问,并将它们重定向到登录视图。成功登录后,我想将用户重定向到他们最初请求的视图,而不是默认视图。

我注意到 Router 有一个 renavigate() 函数可以导航到最后一条成功的路线,但最后一条成功的路线是 /auth/login 而不是最初请求的 url.

基本上:我如何访问或确定先前请求的 url?

我真的不想求助于传递查询字符串参数,除非我真的必须这样做。理想情况下,作为 Router 组件的一部分访问 history 集合会很好,类似于 backbone.history!

您可能会在 docs 中为 Location class 找到您需要的内容。 back() 函数可能会为您完成。

另一种方法是订阅 Location 中的 popstate 事件。 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 对象并订阅任何更改,以便我可以跟踪它们。

这对我有用。将它注入到您的主 App 组件的构造函数中,并在 bootstrap 方法中注册它。 页面加载的第一个 val 应该是原来的 URL。 为了提高效率,我立即取消订阅,因为我不想(也许还)不想收听此服务中的后续路由器事件。 将服务注入其他需要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();
    });
  }

}
  1. 使用 Auth Guards(实现 CanActivate) to prevent unauthenticated users. See official documentation with examples and this blog
  2. 在auth guard中使用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 最终版本。

更新示例使用 Angular 2.2.1

将原始 URL 传递给登录组件的 Auth Guard:

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