Angular и Firebase: Как сохранить пользователя вошедшим в систему, если он / она явно не выходит из системы?

У меня проблема с моим угловым приложением. Если после входа в систему я перехожу на другой веб-сайт и снова возвращаюсь к своему приложению, я выхожу из системы.

Даже если я только обновлю страницу, я выйду из системы.

Это мой AuthService:

export class AuthService {

    private isAuthenticated = false;


    constructor(private router: Router, private db: AngularFirestore, private angularFireAuth: AngularFireAuth) {}


    login(authData: AuthData) {

        this.angularFireAuth.auth.signInWithEmailAndPassword(
            authData.email, 
            authData.password
        ).then(result => {
            this.loggedInSuccessfully();
        })
        .catch(error => {
            console.log(error);
        });

    }

    logout() {
        this.loggedOutSuccessfully();
    }

    isAuth() {
        return this.isAuthenticated;
    }



    private loggedInSuccessfully() {
        this.isAuthenticated = true;
        this.router.navigate(['']);
    }

    private loggedOutSuccessfully() {
        this.angularFireAuth.auth.signOut();
        this.router.navigate(['login']);
        this.isAuthenticated = false;
    }

}

... а это класс AuthGuard:

export class AuthGuard implements CanActivate {

    constructor(private authService: AuthService, private router: Router) {}

    canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
        if (this.authService.isAuth()) {
            return true;
        }
        else {
            this.router.navigate(['login']);
            return false;
        }     
    }
} 

Как я могу сохранить пользователя вошедшим в систему, если он / она явно не выходит из системы?

1 ответ

Проблема в вашем коде, так как это поведение по умолчанию переменной isAuthenticated инициализируется как false, и изменяется только после явного вызова login()Функция, которую я предлагаю использовать Replaysubject тип данных для связи между вашим AuthGuard и ваш сервис. Вот пример кода. С помощью этой логики вы можете даже поставить в очередь чтение базы данных, если логика маршрутизации зависит от уровней пользователя, хранящихся в базе данных.

import { ReplaySubject } from 'rxjs'
import { take, tap, map } from 'rxjs/operators';

export class AuthService {
private isAuthenticated: ReplaySubject<boolean> = new ReplaySubject(1)
constructor(private router: Router, private db: AngularFirestore, 
private angularFireAuth: AngularFireAuth) {
    angularFireAuth.authState.subscribe(state => {
        this.isAuthenticated.next(state)
    })
}

login(authData: AuthData) {
    this.angularFireAuth.auth.signInWithEmailAndPassword(
        authData.email,
        authData.password
    ).then(result => {
        this.loggedInSuccessfully();
    })
        .catch(error => {
            console.log(error);
        });
}

logout() {
    this.loggedOutSuccessfully();
}
/**
 * This function will never return a value until the replay subject gets a value, which is assigned only when the auth state changes
 */
isAuth() {
    return this.isAuthenticated.pipe(
        take(1),
        map(authState => !!authState),
        tap(authenticated => {
            if (!authenticated) {
                return false;
            }
            else {
                return true;
            }
        }), );
}

private loggedInSuccessfully() {
    this.isAuthenticated.next(true)
    this.router.navigate(['']);
}

private loggedOutSuccessfully() {
    this.angularFireAuth.auth.signOut();
    this.router.navigate(['login']);
    this.isAuthenticated.next(false)
}}

Ваша охрана может остаться неизменной

Другие вопросы по тегам