首页 > 解决方案 > 无法使用可观察和延迟加载登录

问题描述

我是 Angular 的新手,我正在尝试实现登录功能。

问题是,在我的用户点击登录后,它应该存储令牌,然后重定向到主页,但 canActivate 返回 false。

Obs:我正在使用 observable 因为我需要在登录页面中隐藏我的导航栏,而我发现的最好方法是使用 *ngIf 并获取 isLoggedIn observable 的值。

身份验证服务.ts

import { HttpClient } from "@angular/common/http";
import { Injectable } from "@angular/core";
import { Router } from "@angular/router";
import { ToastrService } from "ngx-toastr";
import { BehaviorSubject, Observable, Subject } from "rxjs";
import { BaseService } from "./base.service";

@Injectable() 
export class AuthService extends BaseService{

private loggedIn: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);

get isLoggedIn(){
    return this.loggedIn.asObservable();
}

constructor(http: HttpClient, private router : Router, private toastr : ToastrService) {
    super(http);
}

login(body: any){
    return this.post('User/login', body).subscribe(
        (res: any) => {
          localStorage.setItem('token', res.token);
          this.loggedIn.next(true);
          this.router.navigate(['/home']);                       
        },
        err => {
            if (err.status)
              this.toastr.error('FAIL!.');}
    )
}

logout(){
    console.log(this.isLoggedIn)
    this.loggedIn.next(false);
    localStorage.removeItem('token');
    this.router.navigate(['/login']);
}
}

home.component.ts

import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { Observable } from 'rxjs';
import { AuthService } from '../services/auth.service';


@Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.scss']
})
export class HomeComponent implements OnInit {

isLoggedIn$!: Observable<boolean> | Promise<boolean> | boolean;

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

ngOnInit(): void {
 this.isLoggedIn$ = this.authService.isLoggedIn;
}

onLogout(){
 this.authService.logout();
}
}

auth.guard.ts

import { Injectable } from '@angular/core';
import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, Router, CanActivateChild } from '@angular/router';
import { ToastrService } from 'ngx-toastr';
import { Observable } from 'rxjs';
import { map, take } from 'rxjs/operators';
import { AuthService } from '../services/auth.service';

@Injectable()
export class AuthGuard implements CanActivate, CanActivateChild {

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

  canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean  {
    return this.authService.isLoggedIn.pipe(
      take(1),
      map((isLoggedIn: boolean) => {
        if (!isLoggedIn) {
          this.router.navigate(['/login']);
          this.toastr.error("User not loged in!");
          return false;
        }
        return true;
      })
    );
  }
}

应用程序路由.module.ts

import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { AuthGuard } from './auth/auth.guard'; 

const routes: Routes = [
  {
    path: '',
    redirectTo: "/login",
    pathMatch: 'full'
  },
  {
    path: 'home', canActivate: [AuthGuard],
    loadChildren: () => import('./home/home.module').then(m => m.HomeModule)
  },
  {
    path: 'login',
    loadChildren: () => import('./login/login.module').then(m => m.LoginModule)
  },
  {
    path: 'registration',
    loadChildren: () => import('./registration/registration.module').then(m => m.RegistrationModule)
  },
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

标签: angular

解决方案


AuthService您应该从中删除LoginModule,因为它会在该模块注入器中创建此服务的另一个副本,并且因此另一个实例没有获得登录状态


推荐阅读