【问题标题】:Angular Async Router GuardsAngular 异步路由器守卫
【发布时间】:2021-03-12 16:16:49
【问题描述】:

我们有一个Router Guard,它检查用户是否登录和管理员 它还应该检查我们发送到服务器的请求是否具有正确的结果。

问题是canActivate函数在服务器请求完成之前就完成了,所以Router Guard总是false。

希望你有办法解决这个问题

 canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
    var user = JSON.parse(localStorage.getItem('currentUser'));
    if (user != null&&!user.isNotAdmin) {
      if(this.userService.isLoggedIn(user)){
          return true;
      }else{
          return false;
      }
    }else{

    // not logged in so redirect to login page with the return url
    this.router.navigate([''], { queryParams: { returnUrl: state.url } });
    return false;
    }

【问题讨论】:

  • 使用带有await的承诺?
  • 如果可能,尽量避免在canActivate 中调用服务器。因为为每个导航进行服务器调用会使您的页面重定向速度变慢。
  • 我试过但不知道。我怎么能用等待来做到这一点?
  • 我遇到了同样的问题,这个帖子可能会有所帮助。 stackoverflow.com/a/51363905/536388
  • 你在本地存储中有一个对象,它只有一个用户是否是管理员的密钥——这绝对没有安全性。

标签: angular


【解决方案1】:

您必须使用async/await 来确保 canActivate 等到您的服务器请求得到解决。这里有一些示例代码可以帮助您:

/* UserService */
isLoggedIn(user): Observable<boolean> {
  // check if user is logged in
  return isUserLoggedIn;
}

/* Guard */
async canActivate(route: ActivatedRouteSnapshot, 
  state: RouterStateSnapshot): Promise<boolean> {
const user = JSON.parse(localStorage.getItem('currentUser'));
if (user !== null && !user.isNotAdmin) {

  const isUserLoggedIn: boolean = await this.userService.isLoggedIn(user).toPromise();
  // toPromise() converts Observable to Promise (async/await only works on Promises)
  // the code 'waits' at the above line till the server request is resolved

  return isUserLoggedIn;

} else {
  // not logged in so redirect to login page with the return url
  this.router.navigate([''], { queryParams: { returnUrl: state.url } });
    return false;
}

如果您想进一步阅读,请参考:

【讨论】:

    【解决方案2】:

    更高版本的 Angular 可以从 canActivate 方法返回一个 Observable,这让这变得更加容易。如果在localStorage 中找不到用户,则立即返回,如果找到用户,则调用服务方法。 pipetap 可以说是用来拦截它,如果它返回false,它也会导航到''

    canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean | Observable<any> {
      const user = JSON.parse(localStorage.getItem('currentUser'));
      if (user === null || user.isNotAdmin) {
        return false;
      }
    
      return this.userService.isLoggedIn(user).pipe(
        tap((isLoggedIn) => {
          if (!isLoggedIn) {
            this.router.navigate([''], { queryParams: { returnUrl: state.url } });
          }
        })
      }
    }
    

    PS:从localStorage 检查管理员状态不是很安全,但当然取决于您的项目是否可以接受风险。

    【讨论】:

      猜你喜欢
      • 2018-01-10
      • 2017-11-22
      • 2023-03-25
      • 1970-01-01
      • 1970-01-01
      • 2019-02-04
      • 2018-12-04
      • 2021-06-01
      • 2018-04-06
      相关资源
      最近更新 更多