我想在firebase身份验证检索用户 token 时显示一个小的加载 Logo ,然后“真正”启动单页应用程序。
到目前为止,我有一个身份验证服务:
constructor(
public afAuth: AngularFireAuth,
) {
this.afAuth.onAuthStateChanged(user => {
if (user) {
this.setCredentials(user)
}
})
}
setCredentials(user: firebase.User) {
return user.getIdTokenResult(true).then(idTokenResult => {
this.credentials = {
userId: idTokenResult.claims.id,
role: idTokenResult.claims.role,
token: idTokenResult.token,
};
// STARTS THE APPLICATION NOW ?
})
}
是否有可能实现这种行为?我已经阅读了有关 APP_INITIALIZER 的信息,但没有成功。我想避免本地存储/ session 存储,而是完全依赖这个初始化。
更新 :
创建了一个初始化函数:
export function initApp(auth: AuthService, afAuth: AngularFireAuth) {
return () => {
return new Promise((resolve) => {
afAuth.user.pipe(
take(1),
).subscribe(user => {
if (user) {
auth.setCredentials(user)
.then(() => resolve())
} else {
resolve();
}
})
});
}
}
并编辑了 AppModule 提供者:
providers: [
interceptorProviders /* my interceptors */,
{
provide: APP_INITIALIZER,
useFactory: initApp,
deps: [AuthService, AngularFireAuth],
multi: true
}
]
仍然需要弄清楚如何添加等待标志,但这是另一个问题。我会尽快更新。
最佳答案
回答我自己的问题
总而言之,我想确保在处理路由之前将与 firebase 用户关联的 token 声明( Angular 色和用户 ID)存储在我的身份验证服务中,因为这些路由中的组件将使用这些凭据。
最后我没有遵循 APP_INITIALIZER 这不是一个很好的解决方案。
认证服务
private _credentials: BehaviorSubject<Credentials> = new BehaviorSubject<Credentials>(null);
public readonly credentials$: Observable<Credentials> = this._credentials.asObservable();
constructor(private afAuth: AngularFireAuth) {
this.afAuth.authState.subscribe(user => {
this._credentials.next(null);
if (user) {
user.getIdTokenResult().then(data => {
const credentials = {
role: data.claims.role,
token: data.token,
userId: data.claims.userId
}
this._credentials.next(credentials);
console.log(credentials);
})
} else {
this._credentials.next({role: null, token: null, userId: null});
}
})
}
get credentials(): Credentials {
return this._credentials.value;
}
在 app.component 中显示等待微调器如果未设置凭据,则下面会阻止显示路由。
在模板中:
<div *ngIf="!(credentials$ | async)" class="logged-wrapper">
<div class="spinner-wrapper">
<mat-spinner class="spinner"></mat-spinner>
</div>
</div>
<router-outlet *ngIf="(credentials$ | async)"></router-outlet>
在组件中:credentials$: Observable<any>;
constructor(
private auth: AuthService,
) {
this.credentials$ = this.auth.credentials$;
}
身份验证takewhile 让我可以确保在进一步操作之前设置我的凭据。
canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot):Promise<boolean> {
return new Promise((resolve) => {
this.auth.credentials$.pipe(
takeWhile(credentials => credentials === null),
).subscribe({
complete: () => {
const credentials = this.auth.credentials
if (!credentials.role) {
this.router.navigate(['/login'], { queryParams: { returnUrl: state.url } })
resolve(false);
}
if (next.data.roles && next.data.roles.indexOf(credentials.role) === -1) {
this.router.navigate(['/']);
resolve(false);
}
resolve(true)
}
})
})
}
关于javascript - 如何在启动 Angular 应用程序之前等待 Firebase 身份验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62099759/