[英]Angular/rxjs: check Auth Data in Guard after page reload/refresh
[英]Angular/rxjs: Auth0 Auth Guard with custom Profile Guard, wait for data to be fetched
I use Auth0 from the latest Auth0 Angular SDK (v.1.8.2.) with Angular 13 and rxjs 7.4.0, and want to do the following:
我使用 Auth0 Guard 和自定義 Profile Guard 來檢查配置文件數據。
問題:如果我刷新頁面,我的 Auth0 Guard 將返回 true,但我的 Profile Guard 將始終返回 false,因為我的應用程序尚未獲取配置文件數據。
export class AuthService {
profile: BehaviorSubject<Profile| undefined> = new BehaviorSubject<Profile| undefined>(undefined);
public readonly profile$: Observable<Profile| undefined> = this.profile.asObservable();
constructor(
@Inject(DOCUMENT) private doc: Document,
public auth0: Auth0Service,
private httpHandler: HttpHandlerService
) {
this.auth0.isAuthenticated$.subscribe((isAuth) => {
if (isAuth) {
this.httpHandler.fetchProfile().subscribe(
(profile: Profile) => this.profile.next(profile))
}
})
}
}
export class ProfileGuard implements CanActivate, CanActivateChild {
constructor(private auth: AuthService, private router: Router) {
}
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): true | UrlTree {
return this.checkProfile(state.url);
}
canActivateChild(childRoute: ActivatedRouteSnapshot, state: RouterStateSnapshot): true | UrlTree {
return this.checkProfile(childRoute, state);
}
checkLogin(url: string): true | UrlTree {
//how "wait" for the auth service to finish fetching the profile data?
if (this.auth.profile.value?.isBaned!== true)
return true;
return this.router.parseUrl('/banned');
}
}
在我的應用程序路由中,我同時使用了 Auth0 Guard 和我的自定義保護,如下所示:
const routes: Routes = [
{ path: 'myProtectedRoute', component: UserComponent, canActivate: [Auth0Guard, ProfileGuard], runGuardsAndResolvers: 'always' }
]
我怎樣才能重寫我的配置文件保護,讓它等待配置文件數據在繼續之前被提取?
提前致謝
您正在嘗試同步使用異步變量,這是不可能的。 因為您的應用不知道isAuthenticated$
何時會解決。 因此,您需要將異步行為轉發到canActivate
。
避免可能導致潛在 memory 泄漏的嵌套訂閱。 請改用switchMap
之類的高階映射運算符。 請參閱此處了解更多信息。 您還可以使用 RxJS function iif
function 有條件地返回可觀察對象。
使用 RxJS map
算子轉換可觀察的發射並返回不同的數據。
import { Observable, iif, of } from 'rxjs';
import { switchMap, map } from 'rxjs/operators';
export class AuthService {
public readonly profile$: Observable<boolean | Profile>;
constructor(
@Inject(DOCUMENT) private doc: Document,
public auth0: Auth0Service,
private httpHandler: HttpHandlerService
) {
this.profile$ = this.auth0.isAuthenticated$.pipe(
switchMap((isAuth) =>
iif(
() => isAuth,
this.httpHandler.fetchProfile().pipe(
map((profile: any) => <Profile>(profile))
),
of(false)
)
)
);
}
}
export class ProfileGuard implements CanActivate, CanActivateChild {
constructor(private auth: AuthService, private router: Router) { }
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean | UrlTree> {
return this.checkProfile(state.url);
}
canActivateChild(childRoute: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<true | UrlTree> {
return this.checkProfile(childRoute, state);
}
checkLogin(url: string): Observable<boolean | UrlTree> {
return this.auth.profile$.pipe(
map((profile: boolean | Profile) =>
!!profile
? profile?.isBaned
? this.router.parseUrl('/banned')
: true
: false
)
);
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.