Ionic4 离子4、角8和HTTP拦截器

Ionic4 离子4、角8和HTTP拦截器,ionic4,angular8,Ionic4,Angular8,我正在用Ionic 4和Angular 8构建移动应用程序,无法使我的HTTP拦截器工作。 我在这里回顾了所有拦截器的示例,但没有一个符合我的需要,或者根本不起作用 与常规Angular 8版本唯一不同的是从存储器读取令牌的第一行。最初的Angular 8代码同步读取这些内容,不需要订阅,因此可以正常工作。这是离子存储,它以异步方式调用本地资源 这是我的密码: intercept(req:HttpRequest,next:HttpHandler):可观察{ 从(this.storage.get(

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

与常规Angular 8版本唯一不同的是从存储器读取令牌的第一行。最初的Angular 8代码同步读取这些内容,不需要订阅,因此可以正常工作。这是离子存储,它以异步方式调用本地资源

这是我的密码:

intercept(req:HttpRequest,next:HttpHandler):可观察{
从(this.storage.get('id\u token')).subscribe(res=>{
const idToken=res;
如果(idToken){
const clone=req.clone({headers:req.headers.set('token',idToken)});
返回next.handle(克隆);
}否则{
log('未经授权的呼叫被重定向到登录页面');
返回next.handle(req.pipe)(
水龙头(
事件=>{
//成功时将http响应记录到浏览器控制台
if(HttpResponse的事件实例){
//log('api调用成功:',事件);
}
},
错误=>{
//在出现故障时将http响应记录到浏览器控制台
if(HttpErrorResponse的错误实例){
如果(error.status==401){
this.router.navigateByUrl('/');
}
}
}
)
);
}
});
}
在此形状中,它进行编译,但我的IDE报告:TS2355(函数必须返回一个值)。
这里出了什么问题或遗漏了什么?我想不出来

好的,看来你要在一个拦截器中做两件事:

  • 添加承载令牌
  • 如果错误代码为401-重定向到主页
此外,您还可以在每次请求时访问存储,这是非常昂贵的

以下是我所做的:

  • 创建一个身份验证服务并在那里管理令牌
  • 在身份验证服务中,有一个存储令牌最后一个值的行为主体
下面是:

// 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);
    }
}
还有另一个错误拦截器:

// 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);
        }));
    }
}
//错误拦截器
从“@angular/core”导入{Injectable};
从'@angular/common/http'导入{HttpInterceptor,HttpRequest,HttpHandler,HttpEvent};
从“rxjs”导入{observatable,throwerr};
从“rxjs/operators”导入{catchError};
从“../services/authentication.service”导入{AuthenticationService};
@可注射()
导出类ErrorInterceptor实现HttpInterceptor{
构造函数(私有authenticationService:authenticationService){}
拦截(请求:HttpRequest,下一步:HttpHandler):可观察{
返回next.handle(request).pipe(catchError(err=>{
如果(错误状态===401){
//如果api返回401响应,则自动注销
this.authenticationService.logout()。然后(()=>{
location.reload();
});
}
const error=err.error.message | err.error.detail | err.statusText;
返回投掷器(错误);
}));
}
}

希望能有所帮助。

好的,看来您正试图在一个拦截器中完成两件事:

  • 添加承载令牌
  • 如果错误代码为401-重定向到主页
此外,您还可以在每次请求时访问存储,这是非常昂贵的

以下是我所做的:

  • 创建一个身份验证服务并在那里管理令牌
  • 在身份验证服务中,有一个存储令牌最后一个值的行为主体
下面是:

// 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);
    }
}
还有另一个错误拦截器:

// 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);
        }));
    }
}
//错误拦截器
从“@angular/core”导入{Injectable};
从'@angular/common/http'导入{HttpInterceptor,HttpRequest,HttpHandler,HttpEvent};
从“rxjs”导入{observatable,throwerr};
从“rxjs/operators”导入{catchError};
从“../services/authentication.service”导入{AuthenticationService};
@可注射()
导出类ErrorInterceptor实现HttpInterceptor{
构造函数(私有authenticationService:authenticationService){}
拦截(请求:HttpRequest,下一步:HttpHandler):可观察{
返回next.handle(request).pipe(catchError(err=>{
如果(错误状态===401){
//如果api返回401响应,则自动注销
this.authenticationService.logout()。然后(()=>{
location.reload();
});
}
const error=err.error.message | err.error.detail | err.statusText;
返回投掷器(错误);
}));
}
}

希望能有所帮助。

是的,我实现了“你的方式”,它终于起作用了。一个问题:为什么要为成功和失败创建两个独立的拦截器,我坚持只创建一个拦截器,对此我很高兴?另一个问题可能是:您是说访问存储非常昂贵。它不是(或者更确切地说不是)在常规的Angular应用程序中,为什么它是在Ionic中?这毕竟是本地资源,立即可用。2个拦截器,因为这是一个分离的关注点。如果将来我需要对错误403(禁止)甚至404做些什么,我可以修改错误拦截器。如果我需要根据JWT令牌中的“观众”字段执行某些操作,我只会编辑JWT拦截器。当然,如果您愿意,可以将其写入一个文件中。在我的例子中,我从2开始,我发现它更可读。任何异步的东西都需要花费一些时间。。。我不知道你的情况,在我的情况下,我使用@ionic/storage,它将用于Android IndexedDB的引擎盖下,而对于iOS,它将使用Web SQL(因为如果iPhone缺少RAM,它将删除你的本地存储,如果你的应用程序的良好功能取决于你存储中的某些内容,你不希望这样)。访问这些层非常耗时……使用RxJS在单个场景中组合不同的请求