【发布时间】:2021-12-16 16:35:55
【问题描述】:
我正在构建一个使用 GraphQL 端点的角度 spa 前端。用户登录后,我在 localstorage 上设置令牌,并在我的 AuthService 上设置身份验证状态。我的想法(来自 React)是当 App 组件安装 ngOnInit 我将请求我查询谁将从存储在本地存储中的令牌返回用户,我想在 AuthService 上设置用户。我面临的问题是我创建了一个受保护的仪表板路由,但 AuthGuard 没有等待 App Component ngOnInit 完成,它将重定向到登录页面。
import {Component, OnDestroy, OnInit} from '@angular/core';
import {MeGQL, User} from "../generated/graphql";
import {AuthService} from "./auth.service";
import {Router} from "@angular/router";
@Component({
selector: 'app-root',
templateUrl: 'app.component.html'
})
export class AppComponent implements OnInit {
title = 'frontend';
loading: boolean = true
private meSubs: any;
constructor(private meQuery: MeGQL, private authService: AuthService, private router: Router) {
}
async ngOnInit() {
this.loading = true
console.log("MONTOU APP")
this.loading = true
return this.meQuery.fetch({}, {
fetchPolicy: "network-only",
}).toPromise()
.then(({data}) => {
console.log("ENTROU NO THEN")
if (data.me) {
console.log(data.me)
this.authService.setUser(data.me)
this.loading = false
}
}).catch(e => {
this.loading = false
console.log("ERROR: ", e)
})
}
}
{{ loading }}
<div *ngIf="loading">Carregando...</div>
<div *ngIf="!loading">
<router-outlet></router-outlet>
</div>
import { Injectable } from '@angular/core';
import {ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot, UrlTree} from "@angular/router";
import {AuthService} from "../auth.service";
import {Observable} from "rxjs";
@Injectable({
providedIn: 'root'
})
export class AuthGuardService implements CanActivate{
constructor(private authService: AuthService, private router: Router) { }
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise<boolean > {
console.log("Auth Guard user mount")
if(!this.authService.isAuthenticated()) {
console.log("Não autenticado")
await this.router.navigate(['/login'])
return false
}
return true
}
}
import {Injectable} from '@angular/core';
import {User, MeQuery, MeDocument, MeQueryVariables} from "../generated/graphql";
import {BehaviorSubject} from "rxjs";
import {Apollo} from "apollo-angular";
export type CurrentUserType = Pick<User, 'id' | 'name' | 'email' | 'active' | 'type'>
@Injectable({
providedIn: 'root'
})
export class AuthService {
private TOKEN_KEY = "AGENDEI_TOKEN"
private currentUser: CurrentUserType | null = null
private _isAuthenticated = new BehaviorSubject(false);
private authSource = new BehaviorSubject<CurrentUserType | null>(null)
constructor(private apollo: Apollo) { }
loginUser(user: CurrentUserType, accessToken: string) {
localStorage.setItem(this.TOKEN_KEY, accessToken)
this.setUser(user)
this._isAuthenticated.next(true)
}
setUser(user: CurrentUserType) {
this.currentUser = user
}
async logout() {
localStorage.removeItem(this.TOKEN_KEY)
await this.apollo.getClient().resetStore()
this._isAuthenticated.next(false);
}
public isAuthenticated(): Boolean {
return this._isAuthenticated.value
}
public getUserFromMeQuery() {
return this.apollo.query<MeQuery, MeQueryVariables>({
query: MeDocument
}).toPromise()
}
}
【问题讨论】:
标签: javascript angular typescript authentication