Angular5 HttpInterceptor 取决于 Observable 的结果 [英] Angular5 HttpInterceptor depending on the result of an Observable

查看:18
本文介绍了Angular5 HttpInterceptor 取决于 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆