我正在尝试使用Angular5和HttpInterceptor
来实现在所有HTTP请求中注入Authorization标头。
我依赖于第三方库(ADAL,此处称为AuthService
),它公开acquireToken()
方法以获取用于承载授权的令牌。
问题是aquireToken()
返回一个observable,我必须订阅才能获得我需要的真实字符串。
因此,我的代码永远不会注入标头,我想是因为next.handle()
在acquireToken()
返回任何值之前执行。
如何确保在检索到令牌后才调用下一个处理程序?
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 }));
}
}
答案 0 :(得分:6)
此代码将完成工作,诀窍是使用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 }));
}
);
}
}
答案 1 :(得分:0)
可能的问题在这里
constructor(private auth: AuthService) { }
拦截器内的提供程序不可用
使用Injector注入您的服务
// 1. import the injector
import { Injectable, Injector } from '@angular/core';
// 2. create a constant of your service
private auth: AuthService;
// 3. add injector into contsructor; remove authService from constructor
constructor(private injector: Injector) { }
// 4. now create instance of your service inside intercept()
intercept() {
const auth = this.injector.get(AuthService);
// 5. now call method on this auth object