21

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

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

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

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

4

4 回答 4

24
  1. 使用 Auth Guards(实现CanActivate)来防止未经身份验证的用户。请参阅带有示例的官方文档和此博客
  2. 在 auth guard 中使用RouterStateSnapshot来捕获请求的 URL。

    canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) 
    {
        // keep the attempted URL for redirecting
        this._loginService.redirectUrl = state.url;
    }
    
  3. 使用路由器成功验证后重定向到该 URL (例如在 中login.component.ts)。例如this._router.navigateByUrl(redirectUrl);

@MichaelOryl 和 @Vitali 的 PS 建议可行,但我的方式更符合 Angular2 最终版本。

于 2016-10-14T02:28:08.880 回答
8

您可能会在该课程的文档中找到您需要的内容Location。该back()功能可能会为您完成。

另一种方法是订阅 中的popstate事件LocationMDN 的文档讨论了您可能期望收到的值。

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对象并订阅任何更改,以便我可以跟踪它们。

于 2015-12-31T15:49:59.350 回答
6

这对我有用。将其注入主 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();
    });
  }

}
于 2016-07-08T11:27:24.260 回答
4

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

有关更多详细信息和工作演示,您可以查看这篇文章

于 2016-12-08T03:06:18.780 回答