【发布时间】:2021-08-02 16:08:14
【问题描述】:
所以我有一个使用 cookie 处理身份验证的 Angular 8 应用程序(使用 Laravel Sanctum 的 Laravel 服务器)。因为我使用的是 cookie,并且我没有在 localStorage 中存储任何用户数据/令牌,所以每次我的应用程序使用存储的 cookie 初始化时,我都必须从服务器获取当前用户。
auth.service.ts
export class AuthService {
public readonly INITIAL_PATH = '/app/dashboard';
public readonly LOGIN_PATH = '/login';
private loggedUserSubject: Subject<User>;
public loggedUser: Observable<User>;
constructor(
private apiService: ApiService,
private http: HttpClient,
private router: Router,
private csrfService: CsrfService,
) {
this.loggedUserSubject = new Subject;
this.loggedUser = this.loggedUserSubject.asObservable();
this.getCurrentUser().subscribe(); // Initial call to server to get current user
}
...
getCurrentUser(): Observable<User> {
return this.http.get<User>(`${config.authUrl}/user`)
.pipe(
tap(user => {
this.loggedUserSubject.next(user);
}),
share()
);
}
isLoggedIn(): Observable<boolean> {
return this.loggedUser.pipe(
tap(user => {
console.log('logged user: ', user);
}),
map(user => !!user),
catchError(() => of(false)),
)
}
...
}
auth.guard.ts
export class AuthGuard implements CanActivate {
constructor(
private _router: Router,
private _authService: AuthService
) { }
canActivate(): Observable<boolean> {
return this._authService.isLoggedIn().pipe(
tap(isLoggedIn => {
if (isLoggedIn) {
this._router.navigate(['/app/dashboard']);
}
}),
map(isLoggedIn => !isLoggedIn)
);
}
}
每当我的 AuthGuard 被击中时,它都必须调用 AuthService.isLoggedIn() 来返回一个 Observable<boolean> 来判断用户是否在内存中。问题是,我返回的 Subject 可能已经发出也可能没有发出一个值,因为我必须向我的服务器发出异步请求以最初获取当前用户。我不能使用 BehaviourSubject 因为 canActivate 返回第一个发出的值...直到服务器响应我才知道。
如何设置以使 AuthGuard.canActivate() 等待我的服务提供经过身份验证的用户?
【问题讨论】:
-
尝试更改保护以返回布尔值。 AFAIK,如果您返回 Observable,它会返回 Observable 并且不会等待 Observable 完成。如果返回布尔值,它会自动等待 Observable 完成,以便返回布尔值。
标签: javascript angular http rxjs