我有个问题。所以,我想在 Angular 中创建一个路由保护,如果用户登录,则不允许用户访问登录页面。如果来自 AuthService 的 BehaviourSubject 发出一个新的用户对象,我会检查他是否登录,但是当我在搜索栏中输入登录页面的 URL,主题发出的用户对象变为空。你知道为什么会这样吗?
@Injectable({
providedIn: 'root'
})
export class LoggedInGuard implements CanActivate {
constructor(private authService: AuthService, private router: Router){}
canActivate(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
return this.authService.user$.pipe(map(user => {
// check if the user object is empty
const isAuth = !(!!Object.keys(user).length);
console.log(isAuth)
if(isAuth) {
return true;
}
// navigate to /books if user is logged in
return this.router.createUrlTree(['/books']);
}));
}
}
这是我的 AuthService 逻辑:
export class AuthService {
private baseUsersUrl =
environment.firebase.databaseURL + MAIN_API_ENDPOINTS.users;
private userSource = new BehaviorSubject<User>(<User>{});
user$ = this.userSource.asObservable();
tokenExpirationTimer!: any;
constructor(private httpClient: HttpClient,private afAuth: AngularFireAuth, private router: Router) { }
login(email: string, password: string){
return this.httpClient.post<AuthResponseData>(MAIN_API_ENDPOINTS.login,{
email: email,
password: password,
returnSecureToken: true
}).pipe(
catchError(errorResponse => {
console.log(errorResponse);
let errorMessage = 'An unknown error occured!';
if(!errorResponse.error || !errorResponse.error.error) {
return throwError(errorMessage);
} else {
errorMessage = 'Email or password is incorrect'
}
return throwError(errorMessage);
}),
tap((resData) => {
this.saveUserData(email, resData.localId, resData.idToken, +resData.expiresIn);
}),
);
}
saveUserData(email: string, localId: string, idToken: string, expiresIn: number) {
const expirationDate = new Date(new Date().getTime() + expiresIn * 1000);
const currentUser: User = {
email,
id: localId,
token: idToken,
tokenExpirationDate: expirationDate
};
//token will expire in 1h
this.autoLogout(expiresIn * 1000);
document.cookie = 'token' + '=' + idToken;
}
autoLogin() {
const idToken = document.cookie.split('=')[1];
if(!idToken) {
return;
}
this.getUserData(idToken).subscribe((user) => {
this.saveUserData(user.users[0].email, user.users[0].localId, idToken, 100);
})
}
getUserData(idToken: string) {
return this.httpClient.post<any>(
MAIN_API_ENDPOINTS.userData,
{idToken: idToken});
}
我以这种方式将这个路由守卫添加到路由中:
const routes: Routes = [
{
path: 'login',
component: LoginComponent,
canActivate: [LoggedInGuard]
}]