Angular Web 组件 http 调用不通过客户端 http 拦截器路由

Mic*_*lds 5 web-component angular-http-interceptors

设置:

我有一个 Web 组件(Angular 10)正在 Angular 10 应用程序中使用。Web 组件对 Web API 进行 Httpclient 调用,以获取一些数据来填充菜单下拉列表。该 Web 组件是使用 Angular 10 制作 Web 组件的标准方法制作的。

Web 组件通过主客户端应用程序中的脚本加载。这是来自父应用程序的 angular.json 文件。

1."scripts":
 [
    "projects/web-component-test/src/assets/plugin.bundle.js"
 ]
Run Code Online (Sandbox Code Playgroud)

一切正常,除了我们收到 401 错误(未经授权),因为端点要求用户登录。通过正常工作,还有其他控件可以根据需要显示下拉列表,它从 API 获取数据呼叫不会被填充。

流程:

  1. 用户访问网站,然后提示登录(使用 keycloak Auth)。
  2. 应用程序加载正常,但 Web 组件尝试加载菜单项时出现 401 错误除外。

来自父应用程序的 Http 调用工作正常;jwt 令牌将添加到标头中以调用受保护的 API。来自子 Web 组件的调用在标头中没有 jwt 令牌,因此会失败并出现 401 错误。

httpinterceptor:我们在主客户端应用程序(Web 控件的父级)上有一个 httpinterceptor 。从主应用程序发出的 Http 调用将通过拦截器进行路由,如果需要,令牌将附加到标头。

从子 Web 组件发出的调用不会触发父应用程序中的拦截器?

问题: 如何从子 Web 组件路由通过父级中的 http 拦截器进行调用,以便可以添加令牌。

我尝试过的事情:如果我这样做,我可以让网络组件正常工作:

  1. 当父级加载时,我将令牌存储在本地存储中
  2. 在 Web 组件上使用 http 拦截器,从本地存储中检索令牌并使用它。

** 有效,但我不想在本地存储中存储安全令牌。

当父组件加载子组件时,将令牌传递到子组件的属性中

** 再次,我可以让它工作,但不是很安全。

小智 1

Web 组件是独立于主代码库的一段代码,因此当您收到来自 Web 组件的请求时,您的主应用程序将无法在拦截器中捕获这些请求。

对我来说,它起作用的一件事是根据每个请求创建不同的自定义事件:

  • 获取请求
  • 做PostRequest
  • 执行请求
  • 删除请求

让我快速引导您了解这些事件的一个示例。

从主应用程序中,我正在侦听是否触发了以下任何事件:

this.popupEl.addEventListener('doPostRequest', (info: HTMLElementEventMap | any) => {
            this.performHttpRequest(info.detail);
        });
Run Code Online (Sandbox Code Playgroud)

请注意,从您的网络组件发送的所有信息都可以在您的主应用程序收到的“详细信息”属性中找到。

从 Web 组件中,我执行以下命令:

this.doPostRequest.emit({
            url: 'the URL to hit',
            endpointParams: {
                user: 'my user',
                password: '******',
            }
        });
Run Code Online (Sandbox Code Playgroud)

注意:您可以更改要发送的参数的结构。这完全取决于你。

这将触发主应用程序中 API 的执行,并且当从主应用程序执行请求时,您的拦截器将完成其工作并添加您在那里拥有的任何 JWT。主应用程序收到响应后,您将需要在 Web 组件中设置一个新属性以将响应传递给它。像这样的东西:

this.popupEl.apiResponse = {
                webComponentInfo: { ...infoReceivedFromYourWebComponent },
                apiDetails: { ...ResponseFromYourBackend}
            };
Run Code Online (Sandbox Code Playgroud)

最后,在您的 Web 组件中,添加一个监听 apiResponse 属性的新输入:

@Input()
    set apiResponse(apiResponse: RequestParams) {
        if (apiResponse.webComponentInfo.url === 'the URL to hit') {
            // Do what you want in your web component, as you know exactly which URL just got executed.
        }
    }
Run Code Online (Sandbox Code Playgroud)

这样,您就可以让主应用程序继续使用拦截器完成其工作,并且 Web 组件不需要处理 JWT 或实际执行请求。您可能需要考虑的一件事是不允许来自 Web 组件的删除请求,除非您且只有您对 Web 组件具有完全控制权。您不会想要任何可以对非常重要的 API 成功执行 DELETE 请求的东西。

希望这可以帮助。