似乎是一个愚蠢的问题,但由于某种原因我无法弄清楚答案。
我有一个身份验证保护,它检查存储在本地存储中的 JWT 令牌的过期时间,并抛出"您的会话已过期"对话框,该对话框将用户重定向到 On Close 登录。
在当前状态下,仅当浏览器在存储中具有此令牌时,才会引发对话框;否则它会直接重定向到登录页面。
canActivate(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot): boolean {
if (!this._auth.isAuthenticated()) {
if (this._auth.hasToken()) {
this._dialogService.openErrorDialog('Your session has expired, please re-login', 0)
.afterClosed()
.subscribe(() => this.navigateToLogin(state.url));
} else {
this.navigateToLogin(state.url);
}
return false;
}
return true;
}
我想实现以下逻辑:当用户浏览某个应用程序页面时令牌过期 ->用户导航到另一个页面 - 抛出>对话框 ->重定向到登录; 但是,如果用户从外部导航到应用程序中的某个页面,它应该直接重定向他登录页面,而不会抛出对话框,即使浏览器本地存储中已经有过期的令牌。
我试图基于此破解一些解决方案,但没有成功 - 虽然我可以从 canActivate 函数返回Observable<boolean>
,但我无法弄清楚如何使 rxjsmap
处理pairwise
的结果 - 所以我可以使用存在以前的 URL 的事实来确定用户来自哪里。
任何帮助非常感谢。
为您创建了堆栈闪电战示例。使用了您在链接中共享的信息并创建了如下所示的服务。
@Injectable({ providedIn: "root" })
export class FirstVisitService {
readonly isFirstVisit = new BehaviorSubject<boolean>(true);
constructor(router: Router) {
router.events
.pipe(
filter(event => event instanceof NavigationEnd),
first()
)
.subscribe((e: NavigationEnd) => {
this.isFirstVisit.next(false);
this.isFirstVisit.complete();
});
}
}
并将其注入 auth.guard 并像这样使用:
constructor(private service: FirstVisitService ) { }
canActivate(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<boolean> | Promise<boolean> | boolean {
if (this.service.isFirstVisit.value) {
console.log("first time");
} else{
console.log("not first time");
}
return true;
}
您必须在应用程序模块中导入它
export class AppModule {
constructor(f : FirstVisitService) {}
}
因此,它会在任何事件发生之前发生并订阅路由器事件。
只需在src/app/app.components.ts
中设置重定向即可。
这个"组件"是 AppModule 被提升后的第一个被提升的组件。
因此,只需将行放在那里,当用户来自外部时,它将始终重定向。
// src/app/app.components.ts
import { Component } from '@angular/core';
import { Router } from '@angular/router';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'],
})
export class AppComponent {
constructor(private router: Router) {
// no matter where the user is going
// just redirect to login!
// this will only run the first time the app bootstraps
this.router.navigateByUrl('/login'); // <--------
}
}