Ionic 4、Angular 8 和 HTTP 拦截器

smo*_*yna 1 ionic4 angular8

我正在使用 Ionic 4 和 Angular 8 构建移动应用程序,但无法使我的 HTTP 拦截器正常工作。我在这里查看了拦截器的所有示例,但没有一个适合我的需要,或者根本不再起作用。

与常规 Angular 8 版本的唯一区别是从存储中读取令牌的第一行。原始的 Angular 8 代码同步读取这些东西并且不需要订阅因此它可以工作。这里是 Ionic 存储,它以异步方式调用本地资源。

这是我的代码:

intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
  from(this.storage.get('id_token')).subscribe(res => {
    const idToken = res;
    if (idToken) {
      const cloned = req.clone({ headers: req.headers.set('token', idToken)});
      return next.handle(cloned);
    } else {
      console.log('Unauthorized calls are redirected to login page');
      return next.handle(req).pipe(
        tap(
          event => {
            // logging the http response to browser's console in case of a success
            if (event instanceof HttpResponse) {
              // console.log('api call success :', event);
            }
          },
          error => {
            // logging the http response to browser's console in case of a failure
            if (error instanceof HttpErrorResponse) {
              if (error.status === 401) {
                this.router.navigateByUrl('/');
              }
            }
          }
        )
      );
    }
  });
}
Run Code Online (Sandbox Code Playgroud)

以这种形式编译,但我的 IDE 报告:TS2355(函数必须返回一个值)。这里有什么问题或缺失?我想不通。

Mon*_*hus 5

好的,看起来您正在尝试在 1 个拦截器中做两件事:

  • 添加不记名令牌
  • 如果错误代码是 401 - 重定向到主页

此外,您将在每次请求时访问存储,这是昂贵的。

这是我所做的:

  • 创建一个身份验证服务并在那里管理令牌
  • 在身份验证服务中有一个 BehaviourSubject 存储令牌的最后一个值

它是这样的:

// 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);
    }
}
Run Code Online (Sandbox Code Playgroud)

authenticationService.currentAuthTokenValue 只是一个返回当前主题值的 getter

public get currentAuthTokenValue(): AuthToken {
    return this.currentAuthTokenSubject.value;
}
Run Code Online (Sandbox Code Playgroud)

还有另一个错误拦截器:

// Error interceptor
import { Injectable } from '@angular/core';
import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent } from '@angular/common/http';
import { Observable, throwError } from 'rxjs';
import { catchError } from 'rxjs/operators';

import { AuthenticationService } from '../services/authentication.service';

@Injectable()
export class ErrorInterceptor implements HttpInterceptor {
    constructor(private authenticationService: AuthenticationService) {}

    intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        return next.handle(request).pipe(catchError(err => {
            if (err.status === 401) {
                // auto logout if 401 response returned from api
                this.authenticationService.logout().then(() => {
                    location.reload();
                });
            }

            const error = err.error.message || err.error.detail || err.statusText;
            return throwError(error);
        }));
    }
}
Run Code Online (Sandbox Code Playgroud)

希望能帮助到你。

  • 2 个拦截器,因为它是关注点分离。如果将来我需要对错误 403(禁止)甚至 404 进行处理,我可以修改错误拦截器。如果我需要根据 JWT 令牌中的“受众”字段执行某些操作,我只会编辑 JWT 拦截器。当然,如果你愿意的话,你可以把它写在1个文件中。就我而言,我从 2 开始,而且我发现它更具可读性。 (2认同)