使用Angular2创建单页应用程序,我会拦截未经身份验证的用户访问自定义RouterOutlet
中的非公共路由并将其重定向到登录视图。成功登录后,我想将用户重定向到最初请求的视图,而不是默认视图。
我注意到Router
有一个renavigate()
函数导航到最后一条成功路线,但最后一条成功路线是/auth/login
而不是最初请求的网址。
基本上:我如何访问或确定以前请求的网址?
除非我真的需要,否则我真的不想求助于传递查询字符串参数。理想情况下,history
组件作为Router
组件的一部分访问backbone.history
集合会很好,类似于node app.js
!
答案 0 :(得分:17)
使用身份验证后卫中的RouterStateSnapshot来捕获请求的网址。
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot)
{
// keep the attempted URL for redirecting
this._loginService.redirectUrl = state.url;
}
使用Router成功进行身份验证时重定向到该网址(例如在login.component.ts
中)。例如。 this._router.navigateByUrl(redirectUrl);
P.S。 @MichaelOryl和@Vitali的建议可行,但我的方式更符合Angular2的最终版本。
答案 1 :(得分:6)
您可以在Location
课程的docs中找到所需内容。 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
对象并订阅任何更改,以便我可以跟踪它们。
答案 2 :(得分:4)
这对我有用。将它注入主应用程序组件的构造函数中,该构造函数已在引导程序方法中注册它。
页面加载的第一个val
应该是原始网址。
我之后取消订阅是为了提高效率,因为我不想(或许还有)想要收听此服务中的后续路由器事件。
将服务注入需要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();
});
}
}
答案 3 :(得分:3)
使用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