javascript - AuthGuard 在 AuthService 之前加载
问题描述
我正在开发一个小型个人应用程序。我将解释我到目前为止所做的事情,最后是我的问题和我的问题。我创建了一个节点服务器和一个 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 可能在 auth 状态更新之前加载,因此用户无权访问“create-list”组件,尽管他最终已登录。
我考虑了两种解决方案,但我不确定它们是否好以及如何实施它们,并想听听您的意见。
- 使用 localStorage (对于这个小问题,这可能是一个矫枉过正的解决方案)
- 向 authGuard 内的服务器(用于身份验证状态)发出 HTTP 获取请求,或者订阅身份验证服务中的观察者(如果是,如何实现?)
有什么想法/解决方案吗?
可以激活(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']);
}
}
身份验证服务.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。
可以激活(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;
}
})
}
推荐阅读
- angular - 无法将服务中的数据放入窗口变量(此)
- mongodb - 我在工作中获得了一个无服务器应用程序,从哪里开始作为菜鸟?
- python - 如何使用 for 循环为列表中的每个项目创建按钮?
- svg - 用于移动设备的 SVG 中的链接
- php - 我正在尝试在数组中查找不重复的元素
- celery - celery max_memory_per_child 是否在链或和弦中工作?
- vba - 如何确定上周五的日期?
- swiftui - 使用 struct id 将收藏夹保存到 UserDefaults
- javascript - 如何使用 Github API 实现 HTML/JS 以将文件更改保存到存储库
- gensim - 调整 LDA 主题模型