Angular:无法在具有受保护路由的组件之间共享数据

问题描述

我正在尝试在受 keycloak 保护的兄弟组件之间共享数据。

我可以使用路由器导航附加状态或数据服务来共享数据,但前提是路线不受保护。

工作代码

  {
    path: 'path',component: ReceiverComponent
  },

我如何分享

  // code from sender
  this.router.navigate(['path'],{ state: { id: 1 } });

  or

  this.dataService.setData(data);

  // code from receiver (on constructor)
  this.router.getCurrentNavigation().extras.state.id

  or

  this.dataService.data?.subscribe(message => this.message = message)

如果我激活守卫,来自服务的状态和数据在接收器组件上都未定义,即使我已登录并具有完全访问权限:

不工作:

  {
    path: 'path',component: ReceiverComponent,canActivate: [AuthGuard],data: { roles: ['user'] },},

我的钥匙圈 AuthGuard:

import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot,Router,RouterStateSnapshot } from '@angular/router';
import { KeycloakAuthGuard,KeycloakService } from 'keycloak-angular';

@Injectable({
  providedIn: 'root',})
export class AuthGuard extends KeycloakAuthGuard {
  constructor(
    protected readonly router: Router,protected readonly keycloak: KeycloakService
  ) {
    super(router,keycloak);
  }

  public async isAccessAllowed(
    route: ActivatedRouteSnapshot,state: RouterStateSnapshot
  ) {
    if (!this.authenticated) {
      await this.keycloak.login({
        redirectUri: window.location.origin + state.url,});
    }

    const requiredRoles = route.data.roles;

    if (!(requiredRoles instanceof Array) || requiredRoles.length === 0) {
      return true;
    }

    if (requiredRoles.every((role) => this.roles.includes(role))) {
      return true;
    } else {
      this.router.navigate(['access-denied']);
      return false;
    }
  }
}

Keycloak 在拒绝/授权访问受保护路由方面工作正常。

似乎状态历史在受保护的路由上丢失了,例如 AUthGuard/Keycloak 在中间“消耗”共享的数据,但我不明白为什么这会影响服务层。

我是 angular 新手,所以也许我做错了什么,我不知道是否与 keycloak 相关,authguard 配置或其他什么。谢谢各位。

我想要的:

使用 authguard 并能够使用状态、服务等在非相关组件之间共享数据。

版本:

角度:11.2.13 钥匙披风:13.0.0 keycloak-角度:8.2.0 keycloak-js: 13.0.0,

解决方法

您的守卫不对您尝试共享的数据负责,仅负责允许/拒绝访问路线。通常,对于这些情况,您只需将尝试共享的数据放在服务上。无论您是否登录,您都可以从需要它的组件访问该数据(这只是客户端的某种状态,与向某些经过身份验证的端点询问数据不同)。>

另一方面,如果您只想将一些静态数据传递给特定路由,您可以通过该路由的 data 对象来实现,然后通过以下方式在您的组件上访问它激活路由。像这样:

constructor(private route: ActivatedRoute) {}

ngOnInit() {
    this.route.data.subscribe(myData => console.log(myData));
}

尽管如此,还有一些其他方法可以将一些数据从一个页面传递到另一个页面,例如使用查询参数,这也可能有助于您实现目标。检查 Angular Guide 中的此示例。