[英]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 可能在更新身份驗證狀態之前加載,因此用戶無權訪問“創建列表”組件,盡管他最終已登錄。
我想到了兩種解決方案,但我不確定它們是否好以及如何實施它們,並想聽聽您的意見。
任何想法/解決方案?
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”字段設為主題,就像“userAuthDetailsSubject”一樣,並在服務器響應時更新其值。
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;
}
})
}
題外話:
import("@angular/router").UrlTree
? 你可以像import { UrlTree } from '@angular/router';
一樣使用 import import { UrlTree } from '@angular/router';
return this.router.createUrlTree(['/login']);
而不是在你的 canActivate 中創建一個新的異步進程主題:如果你調用直接鏈接,你必須解決身份驗證。 如果您調用鏈接或 F5 重新加載瀏覽器將丟失內存中的所有數據。 如果您使用任何令牌進行身份驗證,則值得保存到 localStore 並從此處恢復。 Ofc,如果您打開新選項卡,則在身份驗證后,此新選項卡將在沒有身份驗證默認值的情況下新建,就像您在當前選項卡上使用 F5 一樣。 每個標簽都有不同的生活。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.