Angular CanActivate重定向以登录浏览器刷新Firebase

时间:2018-07-05 09:26:36

标签: angular typescript firebase angular5

使用angularfire2和firebase的Angular 5身份验证应用程序。该应用程序可以使用应用程序内链接正常浏览。但是,如果我点击浏览器刷新,它将重定向我回到“登录”页面。因为我使用firebase成功登录后,即使true时,allowed总是返回False。

AuthInfo

export class AuthInfo {  
    constructor(public $uid: string) {}

    isLoggedIn() {
        // console.log(this.$uid);
        return !!this.$uid;
    }
}

AuthService

import { Injectable } from '@angular/core';
// tslint:disable-next-line:import-blacklist
import {Observable, Subject, BehaviorSubject} from 'rxjs/Rx';
import {AngularFireAuth } from 'angularfire2/auth';
import { AuthInfo } from '../security/auth-info' ;
import {Router} from '@angular/router';
import * as firebase from 'firebase/app';

@Injectable()
export class AuthService {
  static UNKNOWN_USER = new AuthInfo(null);
  authInfo$: BehaviorSubject<AuthInfo> = new BehaviorSubject<AuthInfo>(AuthService.UNKNOWN_USER);

  constructor(private afAuth: AngularFireAuth, private router: Router) {}
    login(email, password): Observable<AuthInfo> {
        return this.fromFirebaseAuthPromise(this.afAuth.auth.signInWithEmailAndPassword(email, password));
    }

    // signUp(email, password) {
    //  return this.fromFirebaseAuthPromise(this.afAuth.auth.createUserWithEmailAndPassword(email, password));
    // }

    fromFirebaseAuthPromise(promise): Observable<any> {
        const subject = new Subject<any>();
        promise
              .then(res => {
                    const authInfo = new AuthInfo(this.afAuth.auth.currentUser.uid);
                    this.authInfo$.next(authInfo);
                    subject.next(res);
                    subject.complete();
                    // console.log(res);
                },
                err => {
                    this.authInfo$.error(err);
                    subject.error(err);
                    subject.complete();
                });
        return subject.asObservable();
    }

    logout() {
        this.afAuth.auth.signOut();
        this.authInfo$.next(AuthService.UNKNOWN_USER);
        this.router.navigate(['/login']);
    }
    refresh() {
        const url = window.location.href;
    } 
}

AuthGuard

import {tap, take, map} from 'rxjs/operators';
import {CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, Router} from '@angular/router';
// tslint:disable-next-line:import-blacklist
import {Observable} from 'rxjs/Rx';
import {Injectable} from '@angular/core';
import {AuthService} from '../security/auth-service';
import { Location } from '@angular/common';
import { auth } from 'firebase';
import { log } from '@firebase/database/dist/src/core/util/util';

@Injectable()
export class AuthGuard implements CanActivate {
    redirectUrl: string;
    currentURL= '';
    constructor(private authService: AuthService, private router: Router) {}

    canActivate(route: ActivatedRouteSnapshot,
                state: RouterStateSnapshot): Observable<boolean> {

        // tslint:disable-next-line:no-unused-expression
        console.log(this.authService.authInfo$);

        return this.authService.authInfo$.pipe(
            map(authInfo => authInfo.isLoggedIn()),
            take(1),
            tap(allowed => {
                if  (!allowed) {
                    console.log(allowed);
                     this.router.navigate(['/login']);
                }
            }),
        );
    }
}

1 个答案:

答案 0 :(得分:2)

authInfo$UNKNOWN_USER初始化,这将始终使第一个触发值不为真,重新加载时,您仅采用第一个值take(1),这是默认值。

一种解决方案是使第一个值null并在防护中使用的Observable中过滤null值:

AuthService

...
new BehaviorSubject<AuthInfo>(null);
...

AuthGuard

...
return this.authService.authInfo$.pipe(
  filter(_ => _ !== null),
  map(authInfo => authInfo.isLoggedIn()),
  take(1),
...

这样,只有具有警卫意义的值才会被触发。