首页 文章

Angular canActivate重定向到浏览器刷新Firebase登录

提问于
浏览
0

使用angularfire2和firebase的Angular 5身份验证应用 . 该应用程序使用应用程序内链接可以很好地导航 . 但是,如果我点击浏览器刷新,它会将我重定向回登录页面 . 即使是真的,allow也总是返回False,因为我使用firebase成功登录 .

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 回答

  • 2

    authInfo$ 初始化为 UNKNOWN_USER ,它将始终使第一个触发值不为真,重新加载时只取第一个值 take(1) 这是默认值 .

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

    AuthService

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

    AuthGuard

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

    这样,只会触发对守卫有意义的值 .

相关问题