Angular 5,Firebase,HttpClient拦截器奇怪的可观察到的问题

时间:2018-06-24 23:58:19

标签: angular firebase firebase-authentication angular5

我在这里遇到了一个非常奇怪的问题,即Firebase身份验证,HTTP客户端拦截器和可观察对象。基本上,如果我使用“ return this.afAuth.idToken;”在我的auth.service.ts中,并在HttpInterceptor中使用此返回的令牌,注销后会收到多个调用。可以这么说,登录后,我访问了一个使用HttpClient 5次的页面,注销后恰好执行了5个额外的调用。对于我访问的每个页面,感觉就像是多个订阅卡在了内存中(计算每次访问)。然后在身份验证状态(注销)更改后再次执行它们?

因此,这些是我单击注销后执行的调用。我在会话期间访问了这些页面的次数就是这个次数。

这是我的auth.service.ts

import { Injectable } from '@angular/core';
import { environment } from '../../environments/environment';
import { Router } from '@angular/router';
import * as firebase from 'firebase/app';
import { AngularFireAuth } from 'angularfire2/auth';
import { AngularFirestore, AngularFirestoreDocument } from 'angularfire2/firestore';

import { Observable } from 'rxjs/Observable';
import { switchMap } from 'rxjs/operators';
import { fromPromise } from 'rxjs/observable/fromPromise';

import { User } from './user';

@Injectable()
export class AuthService {

  user: Observable<User>;

  constructor(private afAuth: AngularFireAuth,
          private afs: AngularFirestore,
          private router: Router) {
  }

  googleLogin() {
    const provider = new firebase.auth.GoogleAuthProvider()
    return this.oAuthLogin(provider);
  }

  signOut() {
    this.afAuth.auth.signOut().then(() => {
        this.router.navigate(['/']);
    });
  }

  // Used by the http interceptor to set the auth header
  getUserIdToken(): Observable<string> {

    return this.afAuth.idToken;
  }

}

这是我注册的http接受器:

providers: [
ProfileService,
AuthService, 
{ provide: HTTP_INTERCEPTORS, useClass: TokenInterceptor, multi: true }, 
{ provide: ErrorHandler, useClass: AppErrorHandler }
 ]

这是令牌拦截器:

import { Injectable, Injector, OnDestroy } from '@angular/core';
import {
  HttpRequest,
  HttpHandler,
  HttpEvent,
  HttpInterceptor
} from '@angular/common/http';
import 'rxjs/add/operator/mergeMap';

import { AuthService } from './auth.service';
import { Observable } from 'rxjs/Observable';
import { switchMap, mergeMap } from 'rxjs/operators';

import * as firebase from 'firebase/app';
import { Subject } from 'rxjs/Subject';

@Injectable()
export class TokenInterceptor implements HttpInterceptor, OnDestroy {

    auth: AuthService;
    result: Observable<HttpEvent<any>>;

    constructor(private inj: Injector) {}

    intercept(request: HttpRequest<any>, next: HttpHandler) :     Observable<HttpEvent<any>> {

        if (request.url.indexOf('oauthCallback') > -1 ) { 
            return next.handle(request) 
        }

        this.auth = this.inj.get(AuthService) // inject the authservice manually (see https://github.com/angular/angular/issues/18224)

       if (this.auth.getUserIdToken() === null)
            return next.handle(request);

        this.result = this.auth.getUserIdToken().pipe(
            switchMap(token => {
                request = request.clone({
                    setHeaders: {
                    Authorization: 'Bearer ' + token
                    }
                });    

                return next.handle(request);
            })
        )

        return this.result;

    }

    ngOnDestroy() {
    }
}

现在,我找到了一种解决注销后问题的方法,但是那样会导致其他问题。

在我的auth.service.ts中,我也可以通过这种方式返回令牌:

getUserIdToken(): Observable<string> {
    //return this.afAuth.idToken;

    if (this.afAuth.auth.currentUser === null)
      return null;

    return fromPromise ( this.afAuth.auth.currentUser.getIdToken() );
  }

其他所有内容均保持不变。但是,通过这种方式,无需等待令牌即可执行初始调用。可以这么说,我直接在使用HttpClient的某些页面上刷新浏览器,第一次调用没有附加令牌。它不等待观测站返回令牌。 firebase需要大约一秒钟的时间才能返回令牌/登录状态。

带有“返回this.afAuth.idToken;”没有令牌我永远不会接到电话。

如果您能指出我正确的方向,将不胜感激。谢谢。

0 个答案:

没有答案