我正在开发一个 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/