簡體   English   中英

Angular/rxjs:帶有自定義 Profile Guard 的 Auth0 Auth Guard,等待獲取數據

[英]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' }
]

我怎樣才能重寫我的配置文件保護,讓它等待配置文件數據在繼續之前被提取?

提前致謝

  1. 您正在嘗試同步使用異步變量,這是不可能的。 因為您的應用不知道isAuthenticated$何時會解決。 因此,您需要將異步行為轉發到canActivate

  2. 避免可能導致潛在 memory 泄漏的嵌套訂閱。 請改用switchMap之類的高階映射運算符。 請參閱此處了解更多信息。 您還可以使用 RxJS function iif function 有條件地返回可觀察對象。

  3. 使用 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM