当用户到达我的应用程序中的路由时,该路由受到特殊保护,我将其重定向到登录路由,以便执行身份验证。
然而,在成功认证后,我不想将她重新引导回她最初到达的路线。
如何在Angular中保留中间路由状态,然后重定向到它?
通过路由状态我的意思如下:
答案 0 :(得分:1)
稍微使用路由器之后,我终于设法实现了我想要的解决方案。我将在这里与你分享。
所以这是IntermediateNavigationService
的实现:
import {Subscription} from 'rxjs/Subscription';
import {NavigationCancel, NavigationEnd, Router} from '@angular/router';
import {Injectable} from '@angular/core';
@Injectable()
export class IntermediateNavigationService {
private savedUrl: string;
private routerSubscription: Subscription;
constructor (private router: Router) {
}
startWatch () {
this.routerSubscription = this.router.events
.subscribe(event => {
if (event instanceof NavigationCancel) {
// Saving URL from canceled route.
this.saveUrl(event.url);
} else if (event instanceof NavigationEnd) {
// If user navigates away from sign-in page, clearing saved URL.
if (!event.url.match(/^\/sign-in/)) {
if (this.hasSavedUrl()) {
this.clearSavedUrl();
}
}
}
})
;
}
stopWatch () {
this.routerSubscription.unsubscribe();
}
saveUrl (url: string) {
this.savedUrl = url;
}
hasSavedUrl () {
return !!this.savedUrl;
}
getSavedUrl () {
return this.savedUrl;
}
clearSavedUrl () {
this.savedUrl = null;
}
goToSavedUrl (): Promise<boolean> {
return this.router.navigateByUrl(this.savedUrl).then(result => {
if (result) {
this.clearSavedUrl();
}
return result;
});
}
}
这项服务背后的想法非常简单。当由startWatch()
方法激活时(您应该尽早在应用程序生命周期中执行此操作,例如在AppComponent构造函数中),它会开始监视路由器事件,专门过滤NavigationCancel
和NavigationEnd
个事件
当NavigationCancel
发生时,意味着我们的身份验证路由防护无法导航到目标路由。因此,我们将跳过的URL保存在服务私有变量中。
当NavigationEnd
发生时,我们会检查用户是否离开我们的登录路线。在这种情况下,我们不再对保留已保存的URL感兴趣,因此我们正在清除它。否则,当用户被重定向到他不再感兴趣的URL时,可能会导致奇怪的行为。
成功登录后,我们应该发出以下代码:
if (this.intermediateNavigationService.hasSavedUrl()) {
this.intermediateNavigationService.goToSavedUrl();
} else {
this.navigationService.redirectAfterSignIn();
}
很简短:我们只是检查是否有保存的网址,然后导航到它,如果没有重定向到默认网址。
如果您不再对某个时刻监控状态感兴趣,只需拨打stopWatch()
即可取消路由器事件订阅。可以在成功登录后实际保存资源(如果您不打算将此服务用于与身份验证无关的类似行为)。
如果用户已经过身份验证,则无需致电startWatch()
。
以下是AppComponent
的外观:
import {Component as NgComponent} from '@angular/core';
import {AuthenticationStateService} from './authentication/authentication-state.service';
import {IntermediateNavigationService} from './services/intermediate-navigation.service';
@NgComponent({})
export class MyAppComponent {
constructor (
private authenticationStateService: AuthenticationStateService,
private intermediateNavigationService: IntermediateNavigationService
) {
// Enabling intermediate URL handling.
if (!this.authenticationStateService.isAuthenticated()) {
this.intermediateNavigationService.startWatch();
}
// Listening for authentication event.
this.authenticationStateService.onAuthenticated().subscribe(() => {
this.intermediateNavigationService.stopWatch()
});
}
}
我希望它会帮助别人。
答案 1 :(得分:0)
一种方法是使用服务。
以下是一个示例服务:
import { Injectable } from '@angular/core';
import { IUser } from './user';
import { MessageService } from '../messages/message.service';
@Injectable()
export class AuthService {
currentUser: IUser;
redirectUrl: string;
constructor(private messageService: MessageService) { }
isLoggedIn(): boolean {
return !!this.currentUser;
}
login(userName: string, password: string): void {
if (!userName || !password) {
this.messageService.addMessage('Please enter your userName and password');
return;
}
if (userName === 'admin') {
this.currentUser = {
id: 1,
userName: userName,
isAdmin: true
};
this.messageService.addMessage('Admin login');
return;
}
this.currentUser = {
id: 2,
userName: userName,
isAdmin: false
};
this.messageService.addMessage(`User: ${this.currentUser.userName} logged in`);
}
logout(): void {
this.currentUser = null;
}
}
完整代码在此处:https://github.com/DeborahK/Angular-Routing
但是如果你找不到它......这里是登录组件代码:
import { Component } from '@angular/core';
import { NgForm } from '@angular/forms';
import { Router } from '@angular/router';
import { AuthService } from './auth.service';
@Component({
templateUrl: './app/user/login.component.html'
})
export class LoginComponent {
errorMessage: string;
pageTitle = 'Log In';
constructor(private authService: AuthService,
private router: Router) { }
login(loginForm: NgForm) {
if (loginForm && loginForm.valid) {
let userName = loginForm.form.value.userName;
let password = loginForm.form.value.password;
this.authService.login(userName, password);
if (this.authService.redirectUrl) {
this.router.navigateByUrl(this.authService.redirectUrl);
} else {
this.router.navigate(['/products']);
}
} else {
this.errorMessage = 'Please enter a user name and password.';
};
}
}
要完成身份验证服务:
import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, RouterStateSnapshot, Router, Route,
CanActivate, CanActivateChild, CanLoad } from '@angular/router';
import { AuthService } from './auth.service';
@Injectable()
export class AuthGuard implements CanActivate, CanActivateChild, CanLoad {
constructor(private authService: AuthService,
private router: Router) { }
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
console.log('In canActivate: ' + state.url);
return this.checkLoggedIn(state.url);
}
canActivateChild(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
console.log('In canActivateChild: ' + state.url);
return this.checkLoggedIn(state.url);
}
canLoad(route: Route): boolean {
console.log('In canLoad: ' + route.path);
return this.checkLoggedIn(route.path);
}
checkLoggedIn(url: string): boolean {
if (this.authService.isLoggedIn()) {
return true;
}
// Retain the attempted URL for redirection
this.authService.redirectUrl = url;
this.router.navigate(['/login']);
return false;
}
}