簡體   English   中英

AuthGuard 在 AuthService 之前加載

[英]AuthGuard loaded before AuthService

我正在開發一個小型個人應用程序。 我會解釋直到現在我做了什么,最后我的問題和我的問題。 我創建了一個 Node 服務器和一個 Angular 應用程序。 當 Angular 應用程序啟動時,我正在檢查用戶是否已登錄(通過向服務器發送 http get 請求,請求是在 app.component.ts 中進行的)

      ngOnInit(): void {
    this.authService.checkIfUserSignedIn();
  }

之后在 checkIfUserSignedIn 方法中,我獲得了相關的身份驗證信息,我將其通知給具有身份驗證狀態的感興趣的組件。

this.userAuthDetailsSubject.next(this.userAuthDetails);

此外,我有一個 AuthGuard,它將“創建列表”組件的條目限制為僅經過身份驗證的用戶。 在 AuthGurad 我正在檢查身份驗證狀態:

const authStatus = this.authService.isAuth();
return authStatus;

在菜單 html 組件中,我有以下代碼:

<span routerLink="create-list" *ngIf="userIsAuthenticated"> New List</span>

哪個工作正常。 我的問題是當我手動訪問 localhost:4200/create-list

AuthGuard 可能在更新身份驗證狀態之前加載,因此用戶無權訪問“創建列表”組件,盡管他最終已登錄。

我想到了兩種解決方案,但我不確定它們是否好以及如何實施它們,並想聽聽您的意見。

  1. 使用 localStorage(對於這個小問題,這可能是一個矯枉過正的解決方案)
  2. 在 authGuard 內向服務器發出 HTTP get 請求(用於身份驗證狀態),或者訂閱身份驗證服務中的觀察者(如果是這樣,如何實現?)

任何想法/解決方案?


canActivate (AuthGuard):

canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean | import("@angular/router").UrlTree | import("rxjs").Observable<boolean | import("@angular/router").UrlTree> | Promise<boolean | import("@angular/router").UrlTree> {
    const authStatus = this.authService.isAuth();
    if (authStatus) {
        return true;
    } else {
        this.router.navigate(['/login']);
    }
}

auth.service.ts

@Injectable()
export class AuthService {
    userAuthDetailsSubject = new Subject<UserAuthDetails>();
    userAuthDetails: UserAuthDetails = null;
    private isAuthenticated = false;
    constructor(@Inject(DOCUMENT) private document: Document, private http: HttpClient) {

    };

    public isAuth(): boolean {
        console.log({
            isAuth: this.isAuthenticated
        })
        return this.isAuthenticated;
    }

    signIn() {
        // redirect to signin..
        this.document.location.href = '/auth/google';
    }

    signOut() {
        this.document.location.href = '/auth/logout';
    }

    checkIfUserSignedIn() {
        this.http.get<any>('/auth/current_user').subscribe(res => {
            if (res) {
                this.isAuthenticated = true;
                console.log('assigning true to isAuth')
                this.userAuthDetails = {
                    displayName: res.displayName,
                    email: res.email,
                    uid: res._id
                };
                this.userAuthDetailsSubject.next(this.userAuthDetails);
            } else {
                console.log('User not authenticated')
            }
        })
    }
}

對於此特定問題,您可以將“isAuthenticated”字段設為主題,就像“userAuthDetailsS​​ubject”一樣,並在服務器響應時更新其值。

auth.service.ts

    checkIfUserSignedIn() {
    this.http.get<any>('/auth/current_user').subscribe(res => {
        if (res) {
            this.isAuthenticated.next(true);    //update the value
            console.log('assigning true to isAuth')
            this.userAuthDetails = {
                displayName: res.displayName,
                email: res.email,
                uid: res._id
            };
            this.userAuthDetailsSubject.next(this.userAuthDetails);
        } else {
            console.log('User not authenticated')
        }

    })
}

現在更改您的 authguard,使其不會同步返回 true 或 false。

canActivate (AuthGuard):

    canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): 
         boolean | import("@angular/router").UrlTree | 
          import("rxjs").Observable<boolean | import("@angular/router").UrlTree>| Promise<boolean | import("@angular/router").UrlTree> {


          return this.authService.isAuth().subscribe((logged)=>{
            if (logged) {
              return true;
            } else {
             this.router.navigate(['/login']);
             return false;
            }
          })
       }
         

題外話:

  1. 為什么要使用import("@angular/router").UrlTree 你可以像import { UrlTree } from '@angular/router';一樣使用 import import { UrlTree } from '@angular/router';
  2. CanActive 支持 UrlTree 返回。 return this.router.createUrlTree(['/login']); 而不是在你的 canActivate 中創建一個新的異步進程

主題:如果你調用直接鏈接,你必須解決身份驗證。 如果您調用鏈接或 F5 重新加載瀏覽器將丟失內存中的所有數據。 如果您使用任何令牌進行身份驗證,則值得保存到 localStore 並從此處恢復。 Ofc,如果您打開新選項卡,則在身份驗證后,此新選項卡將在沒有身份驗證默認值的情況下新建,就像您在當前選項卡上使用 F5 一樣。 每個標簽都有不同的生活。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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