在运行时在Angular应用程序中加载config.json文件

时间:2020-08-28 15:51:26

标签: angular keycloak angular-http-interceptors

我有问题,我想问问是否有人可以帮助我:)

在我的应用程序中有一个config.json文件,其中包含一些取决于阶段的信息(例如dev,IN,Prod ...)。

{
  "queryUrl": "http://localhost:4200",
  "commandUrl": "http://localhost:8282",
  "ssoUrl": "https:someurlcode",
  "ssoRealm": "someRealm",
  "ssoClient": "dev"
}

在构建应用程序后,我希望交换此文件,因为在不同阶段它是不同的。 (在Jenkins Build中效果很好)

现在,我编写了一个Keycloak服务,在其中创建令牌:

import { Injectable } from '@angular/core';
// @ts-ignore
import Keycloak from 'keycloak-js';
// @ts-ignore
import * as config from '../../../assets/config.json';

@Injectable({
  providedIn: 'root'
})
export class KeycloakService {

  private keycloakAuth: any;

  private ssoUrl: string;
  private ssoRealm: string;
  private ssoClient: string;

  constructor() {
      this.ssoUrl = config.ssoUrl;
      this.ssoRealm = config.ssoRealm;
      this.ssoClient = config.ssoClient;

  }

  init(): Promise<any> {
    console.log('init ' + this.ssoClient);

    return new Promise((resolve, reject) => {
      this.keycloakAuth =  Keycloak({
        url: this.ssoUrl,
        realm: this.ssoRealm,
        clientId: this.ssoClient
      });
      this.keycloakAuth.init({ onLoad: 'login-required' })
          .then(() => {
            console.log('keycloak success');
            resolve();
          })
          .catch(() => {
            console.log('keycloak error');
            reject();
          });
    });
  }
  getToken(): string {
    return this.keycloakAuth.token;
  }
}

您可能会看到,我是通过import语句加载Json的。如果我现在交换文件,它仍然会使用旧文件->猜想,因为它是在构建时获取的。

接下来这是我的http拦截器:

import {Injectable} from '@angular/core';
import {HttpErrorResponse, HttpEvent, HttpHandler, HttpInterceptor, HttpRequest} from '@angular/common/http';
import {KeycloakService} from './keycloak.service';
import {Observable, throwError} from 'rxjs';
import {catchError, retry} from 'rxjs/operators';
import {Router} from '@angular/router';

/**
 * Passes on the KeyCloak token
 */
@Injectable()
export class KeycloakInterceptor implements HttpInterceptor {

    constructor(private kcService: KeycloakService, private router: Router) {}

    intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        const authToken = this.kcService.getToken() || '';
        request = request.clone({
            setHeaders: {
                Authorization: 'Bearer ' + authToken
            }
        });
        return next.handle(request).pipe(
            retry(1),
            catchError((error: HttpErrorResponse) => {
                if (error.status !== undefined) {
                    this.router.navigate(['/error'], {queryParams: {errorCode: error.status}});
                } else {
                    return throwError(error);
                }
            })
        );
    }
}

,还有来自app.module.ts

的一些见解
   {
      provide: APP_INITIALIZER,
      useFactory: keycloakFactory,
      deps: [KeycloakService],
      multi: true
    },
    {
      provide: HTTP_INTERCEPTORS,
      useClass: KeycloakInterceptor,
      multi: true
    }

....

export function keycloakFactory(keycloakService: KeycloakService) {
  return ()  => keycloakService.init();
}

我尝试了几次,以将其加载到init函数等中,但是总是出现未定义等错误……

希望有人可以帮助我...

干杯杰克

1 个答案:

答案 0 :(得分:0)

Configuration.js

window.securityConfiguration = {
  security: {
    "queryUrl": "http://localhost:4200",
    "commandUrl": "http://localhost:8282",
    "ssoUrl": "https:someurlcode",
    "ssoRealm": "someRealm",
    "ssoClient": "dev"
  }
};

然后在您的应用程序中

return new Promise((resolve, reject) => {
  this.keycloakAuth =  Keycloak({
    url: window.securityConfiguration.ssoUrl,
    realm: window.securityConfiguration.ssoRealm,
    clientId: window.securityConfiguration.ssoClient
  });
相关问题