如何在刷新时获取身份验证保护中的用户和购物车数据?

How to get user and cart data in authentication guard on refresh?

我在 spartacus 店面使用 CheckoutAuthGuard 时遇到问题。当在结帐过程中的任何页面上按下浏览器刷新按钮时,由于缺少用户和购物车信息,守卫将我重定向到登录。

我曾经这样使用过CustomCheckoutAuthGuard

import { Injectable } from '@angular/core';
import {CanActivate, Router} from '@angular/router';
import {
  ActiveCartService,
  AuthRedirectService,
  AuthService,
  RoutingService,
  User,
  UserToken,
} from '@spartacus/core';
import { combineLatest, Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import {CheckoutConfigService} from '@spartacus/storefront';

@Injectable()
export class CustomCheckoutAuthGuard implements CanActivate {
  constructor(
    protected routingService: RoutingService,
    protected authService: AuthService,
    protected authRedirectService: AuthRedirectService,
    protected checkoutConfigService: CheckoutConfigService,
    protected activeCartService: ActiveCartService,
    private router: Router
  ) {}

  canActivate(): Observable<boolean> {
    return combineLatest([
      this.authService.getUserToken(),
      this.activeCartService.getAssignedUser(),
    ]).pipe(
      map(([token, user]: [UserToken, User]) => {
        if (!token.access_token) {
          if (this.activeCartService.isGuestCart()) {
            return Boolean(user);
          }
          if (this.checkoutConfigService.isGuestCheckout()) {
            this.router.navigate(['checkout-login']);
          } else {
            this.routingService.go({ cxRoute: 'login' });
          }
          this.authRedirectService.reportAuthGuard();
        }
        return !!token.access_token;
      })
    );
  }
}

它与斯巴达克斯的默认值 CheckoutAuthGuard 非常相似。我还为所有相关的结帐组件切换了这个守卫:

    CheckoutOrchestrator: {
      component: CheckoutOrchestratorComponent,
      guards: [CustomCheckoutAuthGuard, CartNotEmptyGuard, CheckoutGuard],
    },
    CheckoutProgressMobileTop: {
      component: CheckoutProgressMobileTopComponent,
      guards: [CustomCheckoutAuthGuard, CartNotEmptyGuard],
    },
    CheckoutProgressMobileBottomComponent: {
      component: CheckoutProgressMobileBottomComponent,
      guards: [CustomCheckoutAuthGuard, CartNotEmptyGuard]
    },
    CheckoutProgress: {
      component: CheckoutProgressComponent,
      guards: [CustomCheckoutAuthGuard, CartNotEmptyGuard]
    },
    CheckoutDeliveryMode: {
      component: DeliveryModeComponent,
      guards: [CustomCheckoutAuthGuard, CartNotEmptyGuard, ShippingAddressSetGuard]
    },
    CheckoutPlaceOrder: {
      component: PlaceOrderComponent,
      guards: [CustomCheckoutAuthGuard, CartNotEmptyGuard]
    },
    CheckoutReviewOrder: {
      component: ReviewSubmitComponent,
      guards: [CustomCheckoutAuthGuard, CartNotEmptyGuard]
    },
    CheckoutShippingAddress: {
      component: ShippingAddressComponent,
      guards: [CustomCheckoutAuthGuard, CartNotEmptyGuard, CheckoutDetailsLoadedGuard]
    }

但是在刷新时,来自 ActiveCartService 的用户是 undefined 也是 this.activeCartService.isGuestCart() returns undefined.

这一切都是为了访客结账,不幸的是我无法判断登录用户的行为是什么。这是因为我们使用 CDC,目前 CDC 有一个错误,任何刷新都重定向到主页,所以这个守卫被完全绕过。有关此问题的更多信息 here

谁能给我建议最好在这里尝试什么?也许某些购物车状态需要与本地存储同步,或者 combineLatest 这里的 rxjs 函数是错误的?或者是其他东西?提前致谢!

这是一个已知问题,已在 Spartacus 3.0 版中修复。您可以查看我们打开的问题 here。目前没有计划将此更改移植到 3.0 之前的版本。

此问题是由于 运行 在购物车装载之前进行了警卫检查。

如果您在 3.0 之前需要此解决方案,我建议您使用它的自定义版本覆盖现成的 CheckoutAuthGuard。您应该将 this.activeCartService.isStable() 值添加到 combineLatest 流,并在“购物车稳定”上添加 filterHere你明白我的意思了。

以下是您应该如何提供自定义保护以替换默认保护:

(在 app.module.ts 或 AppModule 中导入的其他模块)

providers: [
     ...,
     {
      provide: CheckoutAuthGuard,
      useClass: CustomCheckoutAuthGuard, //or whatever your guard class is named
    }
]