javascript - Angular 库中提供的 HttpInterceptor 不适用于 Angular 应用程序

标签 javascript angular typescript angular-http-interceptors

我正在开发一个 Angular 库,其中有一个提供 HttpInterceptor 的身份验证模块。主要思想是让这个拦截器在任何导入此身份验证模块的应用程序中自动工作,而无需对其进行任何额外设置。

到目前为止,我有以下内容:

AuthenticationModule

@NgModule({
  imports: [ConcreteAuthModule],
  providers: [
    {
      provide: HTTP_INTERCEPTORS,
      useClass: BearerInterceptor,
      multi: true
    }
  ]
})
export class AuthenticationModule {
  static forRoot(config: AuthConfig): ModuleWithProviders {
    return {
      ngModule: AuthenticationModule,
      providers: [
        {
          provide: AUTH_CONFIG,
          useValue: config
        }
      ]
    };
  }
}

ConcreteAuthModule

@NgModule({
  imports: [ThirdPartyLibModule],
  providers: [
    {
      provide: AuthenticationService,
      useClass: ConcreteAuthService
    }
  ]
})
export class ConcreteAuthModule { }

承载拦截器

@Injectable()
export class BearerInterceptor implements HttpInterceptor {
  constructor(private authService: AuthenticationService) { }

  intercept(
    req: HttpRequest<any>,
    next: HttpHandler
  ): Observable<HttpEvent<any>> {
    const headers: any = {};

    if (this.authService.isUserAuthenticated()) {
      headers.Authorization = `Bearer ${this.singleSignOnService.getUserToken()}`;
    }

    const authReq = req.clone({ setHeaders: headers });

    return next.handle(authReq);
  }
}

从一个测试 Angular 应用程序,我在 AppModule 中以下列方式导入这个模块:

@NgModule({
  declarations: [AppComponent],
  imports: [
    BrowserModule,
    HttpClientModule,
    AuthenticationModule.forRoot({ /* config stuff */ })
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule {}

我检查了一些第三方库是如何做到这一点的,也遇到了一些讨论这个问题的 Stack Overflow 问题,他们都建议创建一个 Angular 模块(我已经有了它:AuthenticationModule) ,然后在其上提供 http 拦截器(也已经有了),最后从 Angular 应用程序导入这个模块(也是这样做的)。

但是,我的应用程序中的任何 http 请求都没有被拦截。

尝试直接从我的测试应用导入 BearerInterceptor 并像这样在 AppModule 上提供它:

import { BearerInterceptor } from 'my-lib':

@NgModule({
  declarations: [AppComponent],
  imports: [
    BrowserModule,
    HttpClientModule,
    AuthenticationModule.forRoot({ /* config stuff */ })
  ],
  providers: [
    {
      provide: HTTP_INTERCEPTORS,
      useClass: BearerInterceptor,
      multi: true
    }
  ],
  bootstrap: [AppComponent]
})
export class AppModule {}

那行得通!但这种解决方法不是我想要的......

最佳答案

您非常接近可行的解决方案。

关键是要查看 AppModule 是如何导入模块的。

  imports: [
    BrowserModule,
    HttpClientModule,
    AuthenticationModule.forRoot({ /* config stuff */ })
  ],

这就是 AppModule 导入 AuthenticationModule 的方式,但是 NgModule提供 HTTP_INTERCEPTORS

您已经在 @NgModule() 装饰器中提供了 token ,但是您的应用程序并未使用该模块。它是由 forRoot() 函数定义的模块。

HTTP_INTERCEPTORS 的声明移至 forRoot() 函数。

试试这个:

@NgModule({
    imports: [ConcreteAuthModule]
})
export class AuthenticationModule {
    static forRoot(config: AuthConfig): ModuleWithProviders {
        return {
            ngModule: AuthenticationModule,
            providers: [
                {
                    provide: AUTH_CONFIG,
                    useValue: config
                }, {
                    provide: HTTP_INTERCEPTORS,
                    useClass: BearerInterceptor,
                    multi: true
                }
            ]
        };
    }
}

关于javascript - Angular 库中提供的 HttpInterceptor 不适用于 Angular 应用程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57690266/

相关文章:

angular - Angular 6 中的浏览器选项卡关闭事件仅适用于 Debug模式

javascript - 使用 JavaScript 下载多个文件(一次下载)

javascript - Google Play 英雄 slider ?

javascript - document.getElementById 不会设置变量

javascript - 处理 ES6 类中的上下文

javascript - 从对象列表中删除项目 - Typescript

javascript - AngularJS 中的 CSS 不透明度动画

angular - 如何在 Angular 6 单元测试中依赖注入(inject)接口(interface)

javascript - 最佳实践 : Nested subscriptions to receive user data?

angularjs - AngularJS 和 Typescript 应用程序的 VSCode gulpfile.js 和 tsconfig.json