Angular5 HttpInterceptor 取决于 Observable 的结果 [英] Angular5 HttpInterceptor depending on the result of an Observable
问题描述
我正在尝试使用 Angular5 和 HttpInterceptor
实现在所有 HTTP 请求中注入授权标头.
I am trying to implement using Angular5 an HttpInterceptor
to inject an Authorization header in all HTTP requests.
我依赖第三方库(ADAL,这里称为 AuthService
),该库公开了一个 acquireToken()
方法来获取用于不记名授权的令牌.
I rely on a third party library (ADAL, here called AuthService
) that exposes a acquireToken()
method to get the token to be used for Bearer authorization.
问题是 aquireToken()
返回一个 observable,我必须订阅才能获得我需要的真实字符串.
The problem is that aquireToken()
returns an observable, and i have to subscribe to get the real string I need.
因此,我的代码从不注入标头,我想是因为 next.handle()
在 acquireToken()
返回任何值之前执行.
Therefore, my code never injects the header, i suppose because next.handle()
is executed before acquireToken()
returns any value.
如何确保仅在检索到令牌后才调用下一个处理程序?
How can i ensure that the next handler is called only after the token has been retrieved?
import { Injectable, Injector } from '@angular/core';
import { HttpEvent, HttpInterceptor, HttpHandler, HttpRequest, HttpHeaders } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import {AuthService} from 'mylibrary';
@Injectable()
export class MyInterceptor implements HttpInterceptor {
constructor(private auth: AuthService) { }
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
let headers = req.headers || new HttpHeaders();
this.auth.acquireToken(req.url)
.subscribe((token: string) => {
headers = headers.append('Authorization', 'Bearer ' + token);
});
return next.handle(req.clone({ headers: headers }));
}
}
推荐答案
这段代码可以解决问题,诀窍是使用 mergeMap
This code will do the job, the trick is using mergeMap
import { Injectable, Injector } from '@angular/core';
import { HttpEvent, HttpInterceptor, HttpHandler, HttpRequest, HttpHeaders } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import { AdalService } from './adal.service';
import 'rxjs/add/operator/mergeMap';
@Injectable()
export class AdalInterceptor implements HttpInterceptor {
constructor(private adal: AdalService) { }
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
// if the endpoint is not registered then pass
// the request as it is to the next handler
const resource = this.adal.GetResourceForEndpoint(req.url);
if (!resource) {
return next.handle(req.clone());
}
// if the endpoint is registered then acquire and inject token
let headers = req.headers || new HttpHeaders();
return this.adal.acquireToken(resource)
.mergeMap((token: string) => {
// if the user is not authenticated then drop the request
if (!this.adal.userInfo.authenticated) {
throw new Error('Cannot send request to registered endpoint if the user is not authenticated.');
}
// inject the header
headers = headers.append('Authorization', 'Bearer ' + token);
return next.handle(req.clone({ headers: headers }));
}
);
}
}
这篇关于Angular5 HttpInterceptor 取决于 Observable 的结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!