Authentication in Angular 2, handling the observables

倖福魔咒の 提交于 2019-12-06 16:40:52

The "problem" is that your method is asynchronous so you need to be careful the way and when you use it.

If you want to use within the activate method of your custom RouterOutlet, you need to leverage observables and reactive programming.

I don't know exactly the way you want to check admin roles:

activate(instruction: ComponentInstruction) {
  return this.userService.getAdmin().flatMap((isAdmin) => {
    if (this.userService.isLoggIn()) {
      if (this._canActivate(instruction.urlPath, isAdmin) {
        return Observable.fromPromise(super.activate(instruction));
      } else {
        this.router.navigate(['Forbidden']);
        return Observable.throw('Forbidden');
      }
    } else {
      this.router.navigate(['Login']);
      return Observable.throw('Not authenticated');
    }
  }).toPromise();
}

_canActivate(url, admin) {
  return this.publicRoutes.indexOf(url) !== -1
    || this.userService.isLoggedIn();
}

In order to optimize the request, you could lazily (and only once) call the request to check if the user is admin or not:

isAdmin:boolean;

getAdmin() {
  if (this.isAdmin) {
    return Observable.of(this.isAdmin);
  } else {
    let headers = new Headers({ 'Content-Type': 'application/json' });
    let options = new RequestOptions({ headers: headers });
    return this.http.get('http://localhost:3000/admin/is_admin.json', options)
      .map(res => res)
      .catch(this.handleError);
   }
}

Another approach will be also to load this hint when authenticating the user. This way, the implementation of the activate method would be simplier:

activate(instruction: ComponentInstruction) {
  if (this.userService.isLoggIn()) {
    if (this.userService.isAdmin()) {
      return super.activate(instruction);
    } else if (this._canActivate(instruction.urlPath, isAdmin) {
      return super.activate(instruction);
    } else {
      this.router.navigate(['Forbidden']);
    }
  } else {
    this.router.navigate(['Login']);
  }
}

_canActivate(url, admin) {
  return this.publicRoutes.indexOf(url) !== -1
    || this.userService.isLoggedIn();
}

I would consider to call getAdmin() somehow as first Step of your app, store the result in a SessionService object which you move around using Dependency Injection. This way any time you need to check the result of getAdmin you can ask the SessionService instance. I hope this helps

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!