Angular AuthGuard 和登录持久性:即使已登录,路由器也会自动重定向到 non-truthy 路由
Angular AuthGuard and login persistence: Router automatically redirects to non-truthy route even if logged in
如标题所示,我想通过 canLoad
保护路由。这在某种程度上起作用。但是,我的代码有两个问题。
这是我的代码片段
AppComponent
ngOnInit(): void {
this.authServ.reauthenticate().subscribe()
}
AuthService
user = new BehaviorSubject<User>(null as any);
reauthenticate(): Observable<User> {
// return HTTP call here and pipe the user data into user BehaviorSubject
}
AuthGuard
canLoad(){
return this.authServ.user.pipe(
map((user) => {
if (!!user?._token) {
return true;
}
this.router.navigate(['/login']);
return false;
})
);
}
如您所料,路由器可以访问用户,但仍会重定向到 /login 路径。知道它不起作用,我 brute-forced 按我的方式对服务器进行两次 HTTP 调用(我知道这通常很糟糕)以诱使系统确认持久用户。这是代码片段。
AuthGuard
canLoad() {
return this.authServ.user.pipe(
switchMap((user) => {
if (!!user && !!user._token) {
return of(user);
}
return this.authServ.reauthenticate();
}),
map((user) => {
if (!!user?._token) {
return true;
}
this.router.navigate(['/login']);
return false;
})
);
}
所以我的问题归结为以下两件事之一:
- 如何确保我只调用 re-tokenizer 端点一次但仍然不会继续在刷新时不被路由?
- 如何才能使 BehaviorSubject 正常工作,直到我收到用户 object?
我检查了以下链接:
和 。但是,在使用 Subject
后,我可能需要在每次访问违反直觉的受保护路由时重新验证用户。
好的,我已经解决了这个问题。我所做的是在 AuthService 中创建一个新的 Subject
。守卫检查 AuthService returns 中的 BehaviorSubject
是否为 null,如果是,我将 switchMap
使用 Subject
。这是代码。
AuthGuard
canLoad() {
return this.authServ.user.pipe(
switchMap((user) => {
if (!!user && !!user._token) {
return of(user);
}
return this.authServ.initialLogin;
}),
map((user) => {
if (!!user?._token) {
return true;
}
this.router.navigate(['/login']);
return false;
})
}
AuthService
user = new BehaviorSubject<User>(null as any);
initialLogin = new Subject<User>();
reauthenticate(): Observable<User> {
// return HTTP call here and pipe the user data into user BehaviorSubject
return this.http.get<User>(URL, {withCredentials: true}).pipe(tap((user) => {
this.initialLogin.next(user);
this.user.next(user);
}))
}
AppComponent
ngOnInit(): void {
this.authServ.reauthenticate().subscribe()
}
这样,我只在项目开始时验证一次
如标题所示,我想通过 canLoad
保护路由。这在某种程度上起作用。但是,我的代码有两个问题。
这是我的代码片段
AppComponent
ngOnInit(): void {
this.authServ.reauthenticate().subscribe()
}
AuthService
user = new BehaviorSubject<User>(null as any);
reauthenticate(): Observable<User> {
// return HTTP call here and pipe the user data into user BehaviorSubject
}
AuthGuard
canLoad(){
return this.authServ.user.pipe(
map((user) => {
if (!!user?._token) {
return true;
}
this.router.navigate(['/login']);
return false;
})
);
}
如您所料,路由器可以访问用户,但仍会重定向到 /login 路径。知道它不起作用,我 brute-forced 按我的方式对服务器进行两次 HTTP 调用(我知道这通常很糟糕)以诱使系统确认持久用户。这是代码片段。
AuthGuard
canLoad() {
return this.authServ.user.pipe(
switchMap((user) => {
if (!!user && !!user._token) {
return of(user);
}
return this.authServ.reauthenticate();
}),
map((user) => {
if (!!user?._token) {
return true;
}
this.router.navigate(['/login']);
return false;
})
);
}
所以我的问题归结为以下两件事之一:
- 如何确保我只调用 re-tokenizer 端点一次但仍然不会继续在刷新时不被路由?
- 如何才能使 BehaviorSubject 正常工作,直到我收到用户 object?
我检查了以下链接:
Subject
后,我可能需要在每次访问违反直觉的受保护路由时重新验证用户。
好的,我已经解决了这个问题。我所做的是在 AuthService 中创建一个新的 Subject
。守卫检查 AuthService returns 中的 BehaviorSubject
是否为 null,如果是,我将 switchMap
使用 Subject
。这是代码。
AuthGuard
canLoad() {
return this.authServ.user.pipe(
switchMap((user) => {
if (!!user && !!user._token) {
return of(user);
}
return this.authServ.initialLogin;
}),
map((user) => {
if (!!user?._token) {
return true;
}
this.router.navigate(['/login']);
return false;
})
}
AuthService
user = new BehaviorSubject<User>(null as any);
initialLogin = new Subject<User>();
reauthenticate(): Observable<User> {
// return HTTP call here and pipe the user data into user BehaviorSubject
return this.http.get<User>(URL, {withCredentials: true}).pipe(tap((user) => {
this.initialLogin.next(user);
this.user.next(user);
}))
}
AppComponent
ngOnInit(): void {
this.authServ.reauthenticate().subscribe()
}
这样,我只在项目开始时验证一次