【问题标题】:Ionic + Angular: Auth0 JWT not sending token on headersIonic + Angular:Auth0 JWT 不在标头上发送令牌
【发布时间】:2020-12-17 21:37:56
【问题描述】:

我正在开发我的第一个 Ionic 应用程序,并且已经完成了身份验证部分。

但是经过身份验证后,当我使用 HttpClientModule 发出请求时,它的标头上没有令牌,并且我从我在 .net Core 中制作的 API 得到 401。

我已经阅读了很多关于这个主题的帖子,但似乎没有解决方案可以解决这个问题。

我认为问题不在于 API,因为如果您在标头上有不记名令牌,它适用于邮递员。

这是我的 app.module.ts 配置:

import { AuthModule } from './auth/auth.module';
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { RouteReuseStrategy } from '@angular/router';

import { IonicModule, IonicRouteStrategy } from '@ionic/angular';
import { SplashScreen } from '@ionic-native/splash-screen/ngx';
import { StatusBar } from '@ionic-native/status-bar/ngx';

import { AppComponent } from './app.component';
import { AppRoutingModule } from './app-routing.module';


import { IonicStorageModule, Storage } from '@ionic/storage';
import { JwtModule, JWT_OPTIONS } from '@auth0/angular-jwt';

export function getAuthScheme(request) {
  return 'Bearer ';
}

export function jwtOptionsFactory(storage) {
  return {
      tokenGetter: () => {
      return storage.get('ACCESS_TOKEN');
    },
    authScheme: getAuthScheme,
    whitelistedDomains: ['localhost:44326', 'https://localhost:44326', 'https://localhost:44326/', 'localhost']
  };
}

@NgModule({
  declarations: [AppComponent],
  entryComponents: [],
  imports: [
    BrowserModule,
    IonicModule.forRoot(),
    AppRoutingModule,
    AuthModule,
    IonicStorageModule.forRoot(),
    JwtModule.forRoot({
      jwtOptionsProvider: {
        provide: JWT_OPTIONS,
        useFactory: jwtOptionsFactory,
        deps: [Storage],
      },
    }),
  ],
  providers: [
    StatusBar,
    SplashScreen,
    { provide: RouteReuseStrategy, useClass: IonicRouteStrategy },
  ],
  bootstrap: [AppComponent],
})
export class AppModule {}

我在创建应用程序时检查了使用 cordova 选项。或许与此有关?


更新: 所以,我已经像 Ronny 所说的那样实现了一个拦截器,但是授权头仍然没有出现。

app.mmodule.ts 和以前一样,但是有这个提供程序:

  providers: [
    { provide: HTTP_INTERCEPTORS, useClass: JwtInterceptorProvider, multi: true },
    { provide: RouteReuseStrategy, useClass: IonicRouteStrategy },
    StatusBar,
    SplashScreen,
  ],

这是我的拦截器类:

import { Storage } from '@ionic/storage';
import {
  HttpInterceptor,
  HttpRequest,
  HttpHandler,
  HttpEvent,
} from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';

@Injectable({
  providedIn: 'root',
})
export class JwtInterceptorProvider implements HttpInterceptor {
  constructor(private storage: Storage) {
    console.log(`Hello from JwtInterceptor`);
  }

  intercept(
    request: HttpRequest<any>,
    next: HttpHandler
  ): Observable<HttpEvent<any>> {
    this.storage.get('ACCESS_TOKEN').then((token) => {
      if (token) {
        const clonedRequest = this.addToken(request, token);
        return next.handle(clonedRequest);
      }
    });

    return next.handle(request);
  }

  private addToken(request: HttpRequest<any>, token: any) {

    if (token) {

      console.log(`*******************************************************`);
      console.log(`Bearer ${token}`);

      const headers = {
        Authorization: `Bearer ${token}`,
      };
      if (request.responseType === 'json') {
        console.log('Json request.');
        headers['Content-Type'] = 'application/json';
      }

      console.log('Header added.');

      console.log(`*******************************************************`);
      return request;

    }

  }

}

它在控制台中显示“已添加标题”。所以它达到了代码。但是标头不会出现在最终请求中。我觉得应用程序中的某些内容在此之后覆盖了标题。 我现在真的很困惑。我很欣赏任何想法。

【问题讨论】:

    标签: angular typescript ionic-framework jwt


    【解决方案1】:

    我设法解决了。 问题出在这里:

    this.storage.get('ACCESS_TOKEN').then(...)

    拦截器忽略此承诺并在 .get() 完成添加标头之前返回请求。

    我只是将令牌存储在我的身份验证类中,因此我将它保存在内存中。 我想让拦截器等待 .get() 应该可以工作。

    【讨论】:

      【解决方案2】:

      您必须将令牌添加到每个请求。创建一个拦截器,验证用户是否拥有令牌,并将其添加到请求中。这是一个例子:

      // JWT interceptor
      import { Injectable } from '@angular/core';
      import { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor } from 
      '@angular/common/http';
      import { Observable } from 'rxjs';
      
      import { AuthenticationService } from '../services/authentication.service';
      
      
      @Injectable()
      export class JwtInterceptor implements HttpInterceptor {
      constructor(private authenticationService: AuthenticationService) {}
      
      intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
          // add authorization header with jwt token if available
          const currentAuthToken = this.authenticationService.currentAuthTokenValue;
          if (currentAuthToken && currentAuthToken.token) {
              const headers = {
                  'Authorization': `Bearer ${currentAuthToken.token}`,
              };
              if (request.responseType === 'json') {
                  headers['Content-Type'] = 'application/json';
              }
              request = request.clone({
                  setHeaders: headers
              });
          }
      
          return next.handle(request);
          }
      }
      

      您需要身份验证服务来管理您的用户数据。在此示例中,为此使用了行为主题。有关详细信息,请参阅此链接:https://jasonwatmore.com/post/2019/06/22/angular-8-jwt-authentication-example-tutorial

      【讨论】:

      • 感谢您的回答!我已经按照您所说的实现了拦截器,并检查了示例教程中的所有内容。但是授权仍然没有出现在标题上。我在这里真的很困惑。我正在更新原始帖子上的代码。
      • 我认为你错过了这一行:request = request.clone({ setHeaders: headers });这就是将标头添加到请求的位置。
      猜你喜欢
      • 2018-12-10
      • 2014-09-02
      • 2021-11-04
      • 2015-09-27
      • 1970-01-01
      • 2018-06-08
      • 2021-08-11
      • 2019-02-27
      相关资源
      最近更新 更多