【问题标题】:Angular HTTP interceptor not modifying HTTP request headersAngular HTTP 拦截器不修改 HTTP 请求标头
【发布时间】:2022-01-03 21:00:05
【问题描述】:

我正在使用 Angular 13,尝试将 JWT 添加到标头以访问后端的受限路由。在后端检查时,JwtInterceptor 似乎没有修改 HTTP 请求标头。 在我的项目中,我只在根 AppModule 中包含了一次 HttpClientModule。我已将一个带有错误捕获的管道函数附加到我的next 对象(在拦截器内部),以便按照在 SO 上有类似问题的人的建议进行调试,但无济于事,为简洁起见,删除了管道函数。

我已经在文件中像 console.log'ing 一样基本,但没有输出可以解释它,所以我怀疑拦截器根本没有触发。

我以前使用过拦截器,但没有遇到过这个问题,所以我很难过。这里唯一的区别是我正在使用 Angular PWA,如果我理解正确,服务工作者不应该阻碍拦截器的行为吗?我知道 POST 请求会属于“缓存破坏”事件?

也许错误在于 PWA 的实施?在这种情况下,我确实遵循了文档。

附件是 HttpInterceptors 的 App Module、Jwtinterceptor 和“Barrel”,我计划在项目中添加更多的拦截器,所以我按照文档的建议创建了 Barrel。

TL;DR
我的 HttpInterceptor (JwtInterceptor) 似乎根本没有触发。这个实现在过去的项目中对我有用,唯一的区别是这个项目是一个 PWA。不确定这是否与 PWA 实施存在冲突或怪癖。 HttpClientModule 在项目中只包含一次。

app.module.ts

//Angular level imports
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { HttpClientModule } from '@angular/common/http';

import { AppRoutingModule } from './app-routing.module';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';

//App level components
import { AppComponent } from './app.component';
import { HomeComponent } from './home/home.component';
import { HeaderComponent } from './header/header.component';
import { AngularMaterialModule } from './_material/material.module';
import { UploadDirective } from './directives/upload.directive';
import { LoginComponent } from './login/login.component';
import { RegisterComponent } from './register/register.component';
import { ThanksComponent } from './thanks/thanks.component';
import { PhotoAlbumsComponent } from './photo-albums/photo-albums.component';
import { DialogComponent } from './dialog/dialog.component';
import { AlbumComponent } from './album/album.component';
import { ServiceWorkerModule } from '@angular/service-worker';
import { environment } from '../environments/environment';
import { ForgotPasswordComponent } from './forgot-password/forgot-password.component';
import { ResetPasswordComponent } from './reset-password/reset-password.component';
import { ThanksBotDownloadComponent } from './thanks-bot-download/thanks-bot-download.component';
import { ErrorBotDownloadComponent } from './error-bot-download/error-bot-download.component';
import { RouterModule } from '@angular/router';
import { httpInterceptorProviders } from './_interceptors/index';

@NgModule({
  declarations: [
    AppComponent,
    HomeComponent,
    HeaderComponent,
    UploadDirective,
    LoginComponent,
    RegisterComponent,
    ThanksComponent,
    PhotoAlbumsComponent,
    AlbumComponent,
    DialogComponent,
    ForgotPasswordComponent,
    ResetPasswordComponent,
    ThanksBotDownloadComponent,
    ErrorBotDownloadComponent,
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    BrowserAnimationsModule,
    FormsModule,
    ReactiveFormsModule,
    AngularMaterialModule,
    ServiceWorkerModule.register('ngsw-worker.js', {
      enabled: environment.production,
      // Register the ServiceWorker as soon as the app is stable
      // or after 30 seconds (whichever comes first).
      registrationStrategy: 'registerWhenStable:30000',
    }),
    HttpClientModule,
    RouterModule,
  ],
  providers: [httpInterceptorProviders],
  bootstrap: [AppComponent],
})
export class AppModule {}

jwt.interceptor.ts

import { Injectable } from '@angular/core';
import {
  HttpRequest,
  HttpHandler,
  HttpEvent,
  HttpInterceptor,
} from '@angular/common/http';
import { Observable, throwError } from 'rxjs';
import { environment } from '@environments/environment';
import { AccountService } from '@app/_services/account.service';


@Injectable()
export class JwtInterceptor implements HttpInterceptor {
  constructor(private accountService: AccountService) {}

  intercept(
    request: HttpRequest<any>,
    next: HttpHandler
  ): Observable<HttpEvent<any>> {
    // add auth header with jwt if user is logged in and request is to the api url
    //console.log("JWT Interceptor");
    const user = this.accountService.currentUserValue;
    const isLoggedIn = user && user.jwt;
    const isApiUrl = request.url.startsWith(environment.apiUrl);
    if (isLoggedIn && isApiUrl) {
      request = request.clone({
        setHeaders: {
          Authorization: `Bearer ${user.jwt}`,
        },
      });
    }

    return next.handle(request);
  }
}

index.ts“桶”文件

/* "Barrel" of Http interceptors */
import { HTTP_INTERCEPTORS } from '@angular/common/http';
import { JwtInterceptor } from './jwt.interceptor';

/* Http interceptor providers in outside-in order */
export const httpInterceptorProviders = [
  { provide: HTTP_INTERCEPTORS, useClass: JwtInterceptor, multi: true },
];

发布请求标头

【问题讨论】:

  • 嗨。 httpInterceptorProviders 是数组吗? [...httpInterceptorProviders] 试试这个
  • @MohammadBabaei 这是正确的 httpInterceptorProviders 是一个数组。将扩展运算符添加到我的 AppModule 中的提供程序数组中?我试过了,以防万一这就是你的意思,但它仍然失败。抱歉,如果这不是您的意思,也许您可​​以澄清一下。
  • 只是为了确认一下,你可以达到 if 条件,对吗?
  • @DerrickRose 到目前为止,我不相信我会达到 if 条件。我确实有一个console.log("JWT Interceptor"); 作为一种非正式的检查方式,但每当我通过网络发送请求时都没有日志。感谢您的回复,如果我可以让该该死的文件注册,我会接受,因为它看起来会起作用并且是迄今为止最全面的回复。
  • @DerrickRose 自从我浏览 SO 以来一直在跟进。接受了您的回复。将我的解决方案贴在您的下方,感谢您的帮助。

标签: angular typescript jwt progressive-web-apps mean-stack


【解决方案1】:

试试headers,而不是setHeaders

request = req.clone({
    headers: req.headers.append('Authorization', `Bearer ${user.jwt}`)
});

虽然这个问题似乎是由于你的条件没有得到满足。

【讨论】:

    【解决方案2】:

    感谢帮助的人。

    这个问题与将我的应用程序转换为 PWA 有关。服务人员正在影响我的令牌拦截器。我在没有 PWA 的情况下重新制作了我的应用程序,并且按预期工作。因此,如果您的拦截器停止工作后服务工作者实现,请务必小心,它实际上可能不是您的拦截器。

    我建议任何有兴趣将其转换为 PWA 的工作应用程序来阅读文档但遵循更全面的教程的人,因为我确实觉得更高级主题的 Angular 文档是在真空中编写的并且缺乏一些上下文。

    【讨论】:

      猜你喜欢
      • 2018-12-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-03-30
      • 2019-12-03
      • 2018-12-24
      相关资源
      最近更新 更多