使用auth.service路由警卫

时间:2018-06-09 22:22:12

标签: angular rxjs angular2-routing angular6

我试图创建一个保护一些延迟加载模块的路由保护,我有一个持有当前用户和JWT令牌的BehaviorSubject的auth服务

当我呼叫守卫时,它首先获得当前用户的默认值,并且仅在下一次尝试它允许用户到达路线。

auth.service.ts:

#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/features/normal_3d.h>
#include <pcl/visualization/cloud_viewer.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <pcl/features/integral_image_normal.h>

int main ()
{
  // load point cloud
  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);

  if (pcl::io::loadPCDFile<pcl::PointXYZ> ("table_scene_mug_stereo_textured.pcd", *cloud) == -1) 
  {
    PCL_ERROR ("Couldn't read file table_scene_mug_stereo_textured.pcd \n");
    return (-1);
  }

  std::cout << "Loaded "
            << cloud->width * cloud->height
            << " data points from test_pcd.pcd with the following fields: "
            << std::endl;

  std::cout << "Input cloud Point Size "
            << cloud->points.size ()            
            << std::endl;

  // organized or unorganized normal estimation
  pcl::PointCloud<pcl::Normal>::Ptr cloud_normals (new pcl::PointCloud<pcl::Normal>);
  if (cloud->isOrganized ())
  {
    std::cout << "Computing normals Inside organized block " << std::endl;
    pcl::IntegralImageNormalEstimation<pcl::PointXYZ, pcl::Normal> ne;
    ne.setInputCloud (cloud);
    ne.setNormalEstimationMethod (ne.AVERAGE_3D_GRADIENT);    
    ne.setNormalSmoothingSize (float (0.03));
    ne.setDepthDependentSmoothing (true);
    ne.compute (*cloud_normals);    
  }
  else
  {
    std::cout << "Computing normals Inside non-organized block " << std::endl;
    pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> ne;
    ne.setInputCloud (cloud);
    pcl::search::KdTree<pcl::PointXYZ>::Ptr tree (new pcl::search::KdTree<pcl::PointXYZ> ());
    ne.setSearchMethod (tree);    
    ne.setRadiusSearch (0.03);
    ne.compute (*cloud_normals);
  }

  std::cout << "cloud_normals Point Size "<< cloud_normals->points.size () << std::endl;

  //write the normals to a PCD file
  pcl::PCDWriter writer;
  writer.write("computed_normals.pcd", *cloud_normals, false);

    // visualize normals
    pcl::visualization::PCLVisualizer viewer("PCL Viewer");
    viewer.setBackgroundColor (0.0, 0.0, 0.0);      
    viewer.addPointCloud< pcl::PointXYZRGB >( cloud, "cloud", 0);

    viewer.addPointCloudNormals<pcl::PointXYZ,pcl::Normal>(cloud, cloud_normals);    

    while (!viewer.wasStopped ())
    {
        viewer.spinOnce ();
    }
    return 0;
}

auth.guaed.ts:

import { Injectable } from '@angular/core';
import { HttpClient, HttpErrorResponse, HttpResponse, HttpHeaders } from '@angular/common/http';
import { Observable, BehaviorSubject } from 'rxjs';
import { map, skip, takeLast, last } from 'rxjs/operators';

import { User } from '../shared/user';
import { environment } from '../../environments/environment';


@Injectable()
export class AuthService {
  private loginUserToken: BehaviorSubject<string>;
  private currentUser: BehaviorSubject<User>;
  constructor(private http: HttpClient) {
    // service init
    this.loginUserToken = new BehaviorSubject(undefined);
    this.currentUser = new BehaviorSubject(undefined);
    this.loginUserToken.next(this.getTokenFromLocalStorege());
    if (this.loginUserToken.value != null) {
      this.getUserFromToken();
    }
  }
  /**
   * getLoginUser
   */
  public getLoginUserAsObservable() {
    return this.currentUser.asObservable();
  }
  public getLoginUserTokenAsObservable() {
    return this.loginUserToken.asObservable();
  }
  public async login(user: User): Promise<any> {
    // tslint:disable-next-line:no-shadowed-variable
    return new Promise<any>(async (resolve: any, reject: any) => {
      try {
        const result: any = await this.http.post(`${environment.server}/api/auth/login`, user).toPromise();
        if (result.massageCode === 1) {
          reject('bedUsername');
        } else if (result.massageCode === 2) {
          reject('bed password');
        } else {
          this.loginUserToken.next(result.token);
          this.getUserFromToken();
          this.saveTokenToLocalStorege(result.token);
          resolve();
        }
      } catch (error) {
        reject('error');
      }
    });
  }
  public getUserFromToken(): void {
    const headers = new HttpHeaders({
      'x-access-token': this.loginUserToken.value
    });
    this.http.get(`${environment.server}/api/auth/userFromToken`, { headers }).toPromise()
      .then((data: User) => {
        this.currentUser.next(data);
      })
      .catch((error) => {
        console.log(error);
      });
  }
  public isLogin(): Promise<boolean> {
    return new Promise((resolve, reject) => {
      this.currentUser.asObservable()
      .subscribe((data) => {
        if (data) {
          resolve(true);
        } else {
          resolve(false);
        }
      }).unsubscribe();
    });
  }
  public saveTokenToLocalStorege(token: string): void {
    localStorage.setItem('chanToken', token);
  }
  public getTokenFromLocalStorege(): string {
    return localStorage.getItem('chanToken');
  }
  public removeTokenFromLocalStrege(): void {
    localStorage.removeItem('chanToken');
  }
}

1 个答案:

答案 0 :(得分:0)

这是因为BehaviourSubject如何运作。当您SubscribeBehaviourSubject时,它会立即返回最后一个值。这就是BehaviourSubject需要默认值的原因。

在您的情况下,AuthGuard一旦激活,它就会调用您的isLogin订阅currentUser的方法,它将返回undefined(具体取决于javascript的顺序)执行)。基本上,您的AuthGuard不会等待您的功能getUserFromToken()完成。

使用ReplaySubject代替BehaviourSubject时,您可以轻松解决此问题。

private currentUser: ReplaySubject<User> = new ReplaySubject(1)

使用值1初始化ReplaySubject,它将缓存当前用户,但在没有用户存在时不会触发。

目前,您的Authguard会等待有效的currentUser值,并且在currentUser未定义时不会触发