Как дела?
Итак, я только начал работать с новейшей версией Angular, используя TypeScript, и у меня возникла проблема при попытке загрузить файл конфигурации в мое приложение.
Вещи go примерно так: я работаю над проектом, который использует MsAdalAngular6Module для Azure аутентификации. Когда я получил проект, все параметры конфигурации были жестко запрограммированы, поэтому я следовал инструкциям: https://devblogs.microsoft.com/premier-developer/angular-how-to-microsoft-adal-for-angular-6-with-configurable-settings/, чтобы использовать пакет в более реалистичном c сценарии. Но затем, как вы увидите в первой ссылке, мне пришлось создать сервис для динамической загрузки моих файлов конфигурации, следуя этим инструкциям: https://devblogs.microsoft.com/premier-developer/angular-how-to-editable-config-files/
После этого дела пошли довольно хорошо, Я был в состоянии загрузить мои файлы конфигурации, без проблем. Но проблема началась, когда мне нужно было создать HttpInterceptor , чтобы вставить токен аутентификации в заголовок каждого запроса. В принципе, я не могу использовать оба одновременно (сервис, который загружает файл конфигурации и HttpInterceptor), иначе я получаю эту ошибку:
Ошибка при попытке загрузить файлы конфигурации
Я предполагаю, что запрос, исходящий от службы конфигурации, выполняется до загрузки MsAdalAngular6Module. Таким образом, когда запрос сделан, у него нет некоторых свойств, которые он должен иметь для того, чтобы он был аутентифицирован MsAdalAngular6Service. Конечно, это всего лишь предположение.
Вот код:
Служба конфигурации
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { environment } from '../environments/environment';
import { IAppConfig } from './models/app-config.model';
@Injectable()
export class AppConfig {
static settings: IAppConfig;
constructor(private http: HttpClient) { }
load() {
const jsonFile = `assets/config/config.${environment.name}.json`;
return new Promise<void>((resolve, reject) => {
this.http.get(jsonFile, { withCredentials: true }).toPromise().then((response: IAppConfig) => {
AppConfig.settings = <IAppConfig>response;
resolve();
}).catch((response: any) => {
reject(`Could not load file '${jsonFile}': ${JSON.stringify(response)}`);
});
});
}
}
Перехватчик Http
import { Injectable } from '@angular/core';
import { HttpInterceptor, HttpHandler, HttpRequest } from '@angular/common/http';
import { mergeMap } from 'rxjs/operators';
import { MsAdalAngular6Service } from 'microsoft-adal-angular6';
@Injectable()
export class InsertAuthTokenInterceptor implements HttpInterceptor {
constructor(private adal: MsAdalAngular6Service) { }
intercept(req: HttpRequest<any>, next: HttpHandler) {
// get api url from adal config
const resource = this.adal.GetResourceForEndpoint(req.url);
if (req.withCredentials){
return next.handle(req);
}
if (!resource || !this.adal.isAuthenticated) {
return next.handle(req);
}
// merge the bearer token into the existing headers
return this.adal.acquireToken(resource).pipe(
mergeMap((token: string) => {
const authorizedRequest = req.clone({
headers: req.headers.set('Authorization', `Bearer ${token}`),
});
return next.handle(authorizedRequest);
}));
}
}
И то, как я использую его в app.module.ts :
...
let adalConfig: any;
export const interceptorProviders =
[
{provide: HTTP_INTERCEPTORS, useClass: InsertAuthTokenInterceptor, multi: true}
];
export function msAdalAngular6ConfigFactory() {
return adalConfig;
}
export function initializeApp(appConfig: AppConfig) {
const promise = appConfig.load().then(() => {
adalConfig = {
tenant: AppConfig.settings.adalConfig.tenant,
clientId: AppConfig.settings.adalConfig.clientId,
endpoints: AppConfig.settings.adalConfig.endpoints,
navigateToLoginRequestUrl: false,
cacheLocation: AppConfig.settings.adalConfig.cacheLocation
};
});
return () => promise;
}
...
Часть поставщиков
...
providers: [
AppConfig,
{
provide: APP_INITIALIZER,
useFactory: initializeApp,
deps: [AppConfig],
multi: true,
},
interceptorProviders,
AuthenticationGuard,
LoaderService,
MsAdalAngular6Service,
{
provide: 'adalConfig',
useFactory: msAdalAngular6ConfigFactory,
deps: []
},
AuthenticationGuard
]
...