首页 > 解决方案 > 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”组件,尽管他最终已登录。

我考虑了两种解决方案,但我不确定它们是否好以及如何实施它们,并想听听您的意见。

  1. 使用 localStorage (对于这个小问题,这可能是一个矫枉过正的解决方案)
  2. 向 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')
            }
        })
    }
}

标签: javascriptangularauthentication

解决方案


对于这个特定问题,您可以将“isAuthenticated”字段设置为类似于“userAuthDetailsS​​ubject”的主题,并在服务器响应时更新其值。

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;
            }
          })
       }
         

推荐阅读