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)
}}
Ваша охрана может остаться неизменной