【问题标题】:Ionic 4 + HttpInterceptor + token离子 4 + HttpInterceptor + 令牌
【发布时间】:2019-10-22 14:09:16
【问题描述】:

我正在尝试使用 Ionic 4 项目中的 HttpInterceptor 对后端的所有 API 调用进行身份验证。令牌通过 NativeStorage 保存。当我进行登录调用时会出现问题。由于还没有可用的令牌,NativeStorage 返回一个中断链的错误:NativeStorageError {code: 2, source: "Native", exception: null}

httpConfig.interceptor.ts

import {
  HttpRequest,
  HttpHandler,
  HttpEvent,
  HttpInterceptor,
  HttpResponse,
  HttpErrorResponse
} from '@angular/common/http';

import { Observable, throwError, from } from 'rxjs';
import { map, catchError, switchMap } from 'rxjs/operators';
import { Injectable } from '@angular/core';
import { LoadingController } from '@ionic/angular';
import { NativeStorage } from '@ionic-native/native-storage/ngx';

const TOKEN_KEY = 'auth-token';

@Injectable()
export class HttpConfigInterceptor implements HttpInterceptor {
  loaderToShow: any;
  loadingPresent = false;
  debug = false;
  constructor(
    public loadingController: LoadingController,
    private storage: NativeStorage
  )
  { }

  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {

      return from(this.storage.getItem(TOKEN_KEY))
        .pipe(
          switchMap(token => {
            if (token) {
                request = request.clone({ headers: request.headers.set('Authorization', 'Bearer ' + token.access_token) });
            }
            if (!request.headers.has('Content-Type')) {
              request = request.clone({ headers: request.headers.set('Content-Type', 'application/json') });
            }

            this.showLoader();

            return next.handle(request).pipe(

              map((event: HttpEvent<any>) => {
                if (event instanceof HttpResponse) {
                  console.log('event--->>>', event);
                }
                this.hideLoader();
                return event;
              }),
              catchError((error: HttpErrorResponse) => {
                this.hideLoader();
                return throwError(error);
              })
            );

          })
        );
  }

  showLoader() {
    console.log("show loader");
    this.loaderToShow = this.loadingController.create({
      message: 'Cargando datos...'
    }).then((res) => {

      this.loadingPresent = true;
      res.present();

      res.onDidDismiss().then((dis) => {
        console.log('Loading dismissed!');
      });
    });
  }

  hideLoader() {
    if(this.loadingPresent) {
      this.loadingController.dismiss();
      this.loadingPresent = false;
    }
  }
}

auth.service.ts

import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Platform } from '@ionic/angular';
import { tap, map } from 'rxjs/operators';
import { NativeStorage } from '@ionic-native/native-storage/ngx';
import { environment } from '../../environments/environment';
import { User } from '../models/user';
import { BehaviorSubject } from 'rxjs';

const TOKEN_KEY = 'auth-token';

@Injectable({
  providedIn: 'root'
})

export class AuthService {
  isLoggedIn = false;
  token:any;

  authenticationState = new BehaviorSubject(false);

  constructor(
    private http: HttpClient,
    private storage: NativeStorage,
    private plt: Platform
  )
  {
    this.plt.ready().then(() => {
      this.checkToken();
    });
  }

  login(login: String, password: String) {
    return this.http.post(environment.API_URL + 'auth/login',
      { login: login, password: password }
    ).pipe(
        map(token => {
          this.storage.setItem(TOKEN_KEY, token)
          .then(
            () => {
              this.authenticationState.next(true);
            },
            error => console.error('Error storing item', error)
          );
        }),
    );
  }

  logout() {
    return this.http.get(environment.API_URL + 'auth/logout')
    .pipe(
      tap(data => {
        return this.storage.remove(TOKEN_KEY).then(() => {
          this.authenticationState.next(false);
        });
      })
    )
  }

  isAuthenticated() {
    return this.authenticationState.value;
  }


  checkToken() {
    this.storage.getItem(TOKEN_KEY).then(res => {
      if (res) {
        this.authenticationState.next(true);
      }
    });
  }
}

当我第一次尝试登录时,它从拦截器返回 NativeStorage 的“找不到令牌”错误 NativeStorageError {code: 2, source: "Native", exception: null}

【问题讨论】:

    标签: javascript token ionic4 angular-http-interceptors cordova-nativestorage


    【解决方案1】:

    当项目不存在时,您尝试访问'TOKEN_KEY' 项目。

    intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
       return from(this.storage.getItem(TOKEN_KEY)) <-- //This causes error
    

    checkToken() {
      this.storage.getItem(TOKEN_KEY).then(res => { <-- //This causes error
        if (res) {
           this.authenticationState.next(true);
        }
      });
    }
    

    您必须初始化'TOKEN_KEY' 的默认值或添加 if else 条件以控制(检查)令牌

    您可以使用this.storage.keys 列表查找您的密钥

    其他错误代码:

    • NATIVE_WRITE_FAILED = 1
    • ITEM_NOT_FOUND = 2
    • NULL_REFERENCE = 3
    • UNDEFINED_TYPE = 4
    • JSON_ERROR = 5
    • WRONG_PARAMETER = 6

    【讨论】:

    • 您好 Onur,感谢您的回答。据我了解,要维护这样的结构,我必须在启动时检查 NativeStorage 中是否存在“TOKEN_KEY”键。如果没有,我必须将其创建为空。在注销的情况下,我必须清空它,而不是删除密钥。我想知道这样的方法是否值得,或者我是否必须寻找另一种方法。
    • @elektropier 不需要另寻他路,你的方式就是做你想做的最好的方式。你需要从那个方向继续。只需确保您的“TOKEN_KEY”存在
    【解决方案2】:

    离子存储中的 get 函数将值返回为 object { value : "token value"}

    所以像这样从存储结果中访问 value 属性

    request = request.clone({ headers: request.headers.set('Authorization', 'Bearer ' + 
                             token.value) });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-07
      • 1970-01-01
      • 2018-12-19
      • 1970-01-01
      • 1970-01-01
      • 2021-04-13
      相关资源
      最近更新 更多