首页 > 解决方案 > Ionic 5 使用 IonicStorage 在 HTTP 调用中获取 JWT 发送标头

问题描述

我正在将 Angular Web 应用程序移植到 Ionic,但我被卡住了。

用例 - 我想获取存储在 IonicStorage 中的 jwt 令牌作为 userAttributes 并将其发送到帖子标题中。

userAttributes = {name:"SomeName",token:**theJWTToken**}

由于 IonicStorage 返回承诺,我无法遵循我之前的流程。我是 Promises 和 Observables 的菜鸟。需要一些关于如何从 IonicStorage 获取令牌到选项变量并在 http post 中发送的建议。

以前我曾经这样做如下

登录服务.ts

 getOptions(){
    let headers = new HttpHeaders({
      'X-AUTH-TOKEN': JSON.parse(localStorage.getItem('userAttributes')).token
    });
    let options = { headers: headers, withCredentials: true };
    return options;
  }

resetTokenLink(){
    var options = this.getOptions();
    return this.http.post(environment.APIBaseURL+"/resendToken",'',options);
  }

verifyMail.page.ts

 resend(){  
    this.loginService.resetTokenLink().subscribe(
      res => {this.showAlert("Success",res['msg'])},
      err => {this.showAlert("Error",err.error)}
    );
  }

标签: angularionic-frameworkpromisejwtlocal-storage

解决方案


在浏览了多种表格和博客之后,我找到了一种方法来实现这一点。

解决方案:我创建了一个 HTTPInterceptor,它拦截所有 HTTP 调用并将其添加到所需的标头中。

拦截器.service.ts

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

import { Observable,from } from 'rxjs';
import {  throwError } from 'rxjs';
import { AlertController } from '@ionic/angular';
import { map, catchError, switchMap } from 'rxjs/operators';

@Injectable({
  providedIn: 'root'
})
export class InterceptorService implements HttpInterceptor  {


  constructor(private alertController: AlertController, private storage: Storage) {}

  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
      return from(this.storage.get('userAttributes'))
          .pipe(
              switchMap(token => {               
                  request = request.clone({ headers: request.headers.set('X-AUTH-TOKEN', token.token ) });
                  request = request.clone({ headers: request.headers.set('Content-Type', 'application/json') });
                  request = request.clone({ url:request.url });
                  return next.handle(request).pipe(
                      map((event: HttpEvent<any>) => {
                          if (event instanceof HttpResponse) {
                              // do nothing for now
                          }
                          return event;
                      }),
                      catchError((error: HttpErrorResponse) => {
                          const status =  error.status;
                          const reason = error && error.error.reason ? error.error.reason : '';

                          this.presentAlert(status, reason);
                          return throwError(error);
                      })
                  );
              })
          );


  }

  async presentAlert(status, reason) {
      const alert = await this.alertController.create({
          header: status + ' Error',
          subHeader: 'Subtitle',
          message: reason,
          buttons: ['OK']
      });

      await alert.present();
  }
}

将拦截器添加到 NGModule 提供程序 - app.modules.ts。

import { HttpClientModule ,HTTP_INTERCEPTORS} from '@angular/common/http';

.
.
other code
.
.

 providers: [
    StatusBar,
    SplashScreen,
    { provide: RouteReuseStrategy, useClass: IonicRouteStrategy },
 --->   { provide: HTTP_INTERCEPTORS, useClass: InterceptorService, multi: true },

  ],

现在完成所有请求都将具有提到的标头。

一些有帮助的参考资料:

https://forum.ionicframework.com/t/ionic-4-storage-token-access-for-http-interceptor/158822

https://ionicacademy.com/ionic-http-interceptor/


推荐阅读