Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angular/29.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Angular 如何在角色保护中等待服务器授权?_Angular_Typescript_Authorization_Angular Guards - Fatal编程技术网

Angular 如何在角色保护中等待服务器授权?

Angular 如何在角色保护中等待服务器授权?,angular,typescript,authorization,angular-guards,Angular,Typescript,Authorization,Angular Guards,在我的应用程序中,用户登录并接收存储在本地存储中的JWT。在用户经过身份验证后,将对服务器进行以下调用,以确定用户的角色和功能(他们可以访问哪些页面) 我的问题是,当用户想要打开一个页面(恢复旧会话、复制选项卡、将URL传递给其他人等)时,应用程序没有授权详细信息,必须首先请求授权详细信息,角色卫士就会介入。这将导致用户被重定向到登录页面 @Injectable({ providedIn: 'root' }) export class RoleGuardService implements

在我的应用程序中,用户登录并接收存储在本地存储中的JWT。在用户经过身份验证后,将对服务器进行以下调用,以确定用户的角色和功能(他们可以访问哪些页面)

我的问题是,当用户想要打开一个页面(恢复旧会话、复制选项卡、将URL传递给其他人等)时,应用程序没有授权详细信息,必须首先请求授权详细信息,角色卫士就会介入。这将导致用户被重定向到登录页面

@Injectable({
  providedIn: 'root'
})
export class RoleGuardService implements CanActivate {

  constructor(public auth: AuthService, public router: Router, public globalConfig: GlobalConfigService) { }

  canActivate(route: ActivatedRouteSnapshot): boolean {

    if (!this.auth.isAuthenticated()) {
      this.router.navigate(['login']);
      return false;
    }

    const expectedFunction = route.data.expectedFunction;

    if (!this.globalConfig.hasFunction(expectedFunction)) {
      this.router.navigate(['login']);
      return false;
    }

    return true;
  }
}
预期功能在routes中定义,例如:

{
    path: 'system-admin', loadChildren: () => SystemAdminModule,
    data: { breadcrumb: 'System Admin', expectedFunction: FunctionType.SystemAdministration }, canActivate: [RoleGuard]
},
GlobalConfigService
中的
hasFunction
主体如下所示:

private authorizedUser: AuthorizedUser = new AuthorizedUser();

public hasFunction(expectedFunction: FunctionType): boolean {
    return !!this.authorizedUser.functions
            && this.authorizedUser.functions.find(f => f === expectedFunction) !== undefined;
}
AuthService
中完成的授权如下所示:

public onAuthorized = new Subject<AuthorizedUser>();

authorize() {
    const url = environment.APIURL + 'auth/currentuser';

    return this.http.get(url).subscribe(
        resp => {
            this.globalConfig.AuthorizedUser = resp;
            this.onAuthorized.next(resp as AuthorizedUser);
        }
    );
}

我相信解决方案是,如果用户经过身份验证,那么应该在评估任何其他内容之前,允许完成授权,从而使其处于等待状态。这只需要在
RoleGuard中发生,还是会贯穿整个身份验证/授权过程?

是的,您可以等待用户在您的guard中进行授权。您需要记住的唯一一件事是不要对用户进行两次授权,这意味着您应该在页面导航之间缓存授权结果

角色守卫.service.ts

canActivate(route: ActivatedRouteSnapshot): boolean | Promise<boolean> {

  if (!this.auth.isAuthenticated()) {
    this.router.navigate(['login']);
    return false;
  }

  return this.auth.authorize().then(result => {
    if (!result) {
      return false;
    }

    const expectedFunction = route.data.expectedFunction;

    if (!this.globalConfig.hasFunction(expectedFunction)) {
      this.router.navigate(['login']);
      return false;
    }

    return true;
  });
}
@Injectable({
  providedIn: 'root',
})
class AuthService {
  ...

  private authorizePromise: Promise<boolean>;

  constructor(private http: HttpClient, private globalConfig: GlobalConfigService) {}

  authorize(): Promise<boolean> {
    if (!this.authorizePromise) {
      const url = environment.APIURL + 'auth/currentuser';
      this.authorizePromise = this.http.get(url)
        .toPromise()
        .then(resp => {
          this.globalConfig.AuthorizedUser = resp;
          this.onAuthorized.next(resp as AuthorizedUser);
          return true;
        })
        .catch(() => false);
    }

    return this.authorizePromise;
  }
}
canActivate(路由:ActivatedRouteSnapshot):布尔值{
如果(!this.auth.isAuthenticated()){
this.router.navigate(['login']);
返回false;
}
返回此.auth.authorize()。然后(结果=>{
如果(!结果){
返回false;
}
const expectedFunction=route.data.expectedFunction;
如果(!this.globalConfig.hasFunction(expectedFunction)){
this.router.navigate(['login']);
返回false;
}
返回true;
});
}
auth.service.ts

canActivate(route: ActivatedRouteSnapshot): boolean | Promise<boolean> {

  if (!this.auth.isAuthenticated()) {
    this.router.navigate(['login']);
    return false;
  }

  return this.auth.authorize().then(result => {
    if (!result) {
      return false;
    }

    const expectedFunction = route.data.expectedFunction;

    if (!this.globalConfig.hasFunction(expectedFunction)) {
      this.router.navigate(['login']);
      return false;
    }

    return true;
  });
}
@Injectable({
  providedIn: 'root',
})
class AuthService {
  ...

  private authorizePromise: Promise<boolean>;

  constructor(private http: HttpClient, private globalConfig: GlobalConfigService) {}

  authorize(): Promise<boolean> {
    if (!this.authorizePromise) {
      const url = environment.APIURL + 'auth/currentuser';
      this.authorizePromise = this.http.get(url)
        .toPromise()
        .then(resp => {
          this.globalConfig.AuthorizedUser = resp;
          this.onAuthorized.next(resp as AuthorizedUser);
          return true;
        })
        .catch(() => false);
    }

    return this.authorizePromise;
  }
}
@可注入({
providedIn:'根',
})
类身份验证服务{
...
私人承诺:承诺;
构造函数(私有http:HttpClient,私有globalConfig:GlobalConfigService){}
授权:承诺{
如果(!本.承诺){
const url=environment.apirl+'auth/currentuser';
this.authorizePromise=this.http.get(url)
.toPromise()
。然后(resp=>{
this.globalConfig.AuthorizedUser=resp;
本。onAuthorized。next(分别作为授权人);
返回true;
})
.catch(()=>false);
}
还这个承诺;
}
}
正如您所看到的,我在AuthService中使用了cached
authorizePromise
,以便缓存授权结果,以便授权只发生一次


以下是

中的一些片段,路由器防护装置可以“等待”。您只需返回一个可观察值,稍后将解析为true/false。在那之前什么都不会发生