提问者:小点点

未捕获(在promise中):错误:静态注入器错误[PublicKeyService]


app.public-key-service.ts


import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { map } from 'rxjs/operators';
import {environment} from '../../../environments/environment';
import { WebStorageStateStore } from 'oidc-client';

@Injectable()
export class PublicKeyService {
  private tenantId = '';
  private jwks_uri = `https://login.microsoftonline.com/${this.tenantId}/discovery/v2.0/keys`;

  constructor(private http: HttpClient) { }

  private getBaseUrl(): string {
    let baseUrl = 'https://' + window.location.hostname;

    if (window.location.port && window.location.port !== '443') {
      baseUrl = baseUrl + ':' + window.location.port;
    }

    return baseUrl;
  }

  private getPublicKeys(): any {
    return this.http.get<{ keys }>(this.jwks_uri);
  }

  public getClientSettings() {

    const metadata = {
      issuer: `https://login.microsoftonline.com/${this.tenantId}/v2.0`,
      authorization_endpoint: `https://login.microsoftonline.com/${this.tenantId}/oauth2/v2.0/authorize`,
      token_endpoint: `https://login.microsoftonline.com/${this.tenantId}/oauth2/v2.0/token`
    };

    const add_signing_keys = function (keys_array) {
      return {
        metadata: metadata,
        singingKeys: keys_array,
        authority: `https://login.microsoftonline.com/${this.tenantId}/oauth2/v2.0/authorize`,
        client_id: `${environment.secureAuthClientId}`,
        redirect_uri: `${this.getBaseUrl()}/auth-callback`,
        post_logout_redirect_uri: this.getBaseUrl(),
        response_type: 'id_token',
        scope: 'openid profile email',
        filterProtocolClaims: true,
        loadUserInfo: false,
        automaticSilentRenew: false,
        checkSessionInterval: 1000000,
        userStore: new WebStorageStateStore({ store: sessionStorage })
      };
    };

    return this.http.get<{ keys }>(this.jwks_uri).pipe(
      map(val => add_signing_keys(val.keys))
    );
  }
}

认证-安全-授权-服务. ts

    import {Injectable, OnDestroy} from '@angular/core';
import {HttpClient} from '@angular/common/http';
import {Observable} from 'rxjs/Observable';
import { catchError, tap } from 'rxjs/operators';
import {environment} from '../../../environments/environment';
import 'rxjs/Rx';

import {UserManager, UserManagerSettings, User, WebStorageStateStore} from 'oidc-client';

import {PublicKeyService} from '../../security/services/app.public-key-service';
import {UserService} from '../../shared/services/user.service';
import {KnownAuthenticationTypes} from '../types/known-authentication-types';
import {Login} from '../types/login';
import {LoginDto} from '../types/login-dto';
import {LoginMap} from '../types/login-map';
import {ChangePassword} from '../../settings/types/change-password';
import {ChangePasswordDto} from '../../settings/types/change-password-dto';
import {ChangePasswordMap} from '../../settings/types/change-password-map';
import {ResetPasswordRequestDto} from '../types/reset-password-request-dto';
import {BaseDto} from '../../shared/types/base-dto';
import * as Oidc from 'oidc-client';
import {Subject} from 'rxjs/Subject';
import {Router} from '@angular/router';
import {KnownRoutePath, KnownEvent} from '../../shared/types/known-routes';

@Injectable()
export class AuthenticationSecureAuthService implements OnDestroy {
  private readonly loginReturnUrlKey: string = 'loginReturnUrlKey';
  private user: User = null;
  private manager: UserManager;

  constructor(private http: HttpClient, private userService: UserService, private router: Router,private publicKeyService:PublicKeyService) {
    Oidc.Log.logger = console;
    Oidc.Log.level = Oidc.Log.INFO;
    this.publicKeyService.getClientSettings().subscribe(
      data =>{   
        console.log(data),
         this.manager = new UserManager(data);
         this.start(); 
    }
  );

  }
  ngOnDestroy() {
    this.stop();
  }

  // Make a call to "login" to web API using id_token from SecureAuth
  loginWithIdToken(idToken: string): Observable<Login> {
    const url = `${environment.apiSecurityOrigin}/security/tokenlogin`;
    const body = {idToken: idToken};

    console.log('About to call web API to fetch user auth token and roles');
    return this.http.post<BaseDto<LoginDto>>(url, body)
      .map(baseDto => {
        console.log('Returned from calling web API to fetch user auth token and roles');
        const vm = LoginMap.toVm(this.extractLoginDto(baseDto.value));
        if (vm.authenticationType === KnownAuthenticationTypes.Authenticated) {
          this.userService.setCurrentUser(vm.authenticationToken, vm.user);
        } else {
          this.userService.clearCurrentUserAndToken();
        }
        return vm;
      })
      .catch(this.handleLoginError);
  }

  isLoggedIn(): boolean {
    return this.user != null && !this.user.expired;
  }

  getClaims(): any {
    return this.user.profile;
  }

  getIdToken(): string {
    return this.user.id_token;
  }

  getLoginReturnUrl(): string {
    let returnUrl: string = sessionStorage.getItem(this.loginReturnUrlKey);
    if (!returnUrl) {
      // Default to workqueues if sessionStorage not set.
      returnUrl = '/workqueues';
    }

    return returnUrl;
  }

  setLoginReturnUrl(returnUrl: string): void {
    sessionStorage.setItem(this.loginReturnUrlKey, returnUrl);
  }

  startAuthentication(): Promise<void> {
    return this.manager.signinRedirect();
  }

  completeAuthentication(): Promise<void> {
    return this.manager.signinRedirectCallback().then(user => {
      this.user = user;
    }, reason => console.log('Error in signinRedirectCallback(): ' + reason));
  }

  private extractLoginDto(body: any) {
    return new LoginDto(body.authenticationToken, body.authentication, body.user);
  }

  private handleLoginError(response: Response | any) {
    return Observable.throw(response);
  }

  private start(): void {
    window.addEventListener('storage', this.storageEventListener.bind(this));
  }

  private storageEventListener(event) {
    if (event.key === KnownEvent.LogoutEventName) {
      // The user logged out of another tab, so log out here.
      console.log('User logged out of another tab, so logging out now.');
      this.router.navigate([KnownRoutePath.Logout]);
    }
  }

  private stop(): void {
    window.removeEventListener('storage', this.storageEventListener.bind(this));
  }

}

auth. Guard.ts

import {Injectable} from '@angular/core';
import {Router, CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, CanLoad, Route} from '@angular/router';
import {Observable} from 'rxjs/Observable';

import {UserService} from '../../shared/services/user.service';
import {AlertService} from '../../shared/services/alert.service';
import {AuthenticationSecureAuthService} from '../../security/services/authentication-secure-auth.service';

@Injectable()
export class AuthGuard implements CanActivate, CanLoad {

  constructor(
    private router: Router,
    private userService: UserService,
    private alertService: AlertService,
    private authService: AuthenticationSecureAuthService
    ) {
  }

  canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
    return this.checkLoggedIn(state.url);
  }

  canLoad(route: Route): boolean | Observable<boolean> | Promise<boolean> {
    console.log(route.path);
    return this.checkLoggedIn(route.path);
  }

  private checkLoggedIn(url: string): boolean {
    const loggedIn = this.userService.isLoggedIn();
    const sessionCurrent = this.userService.isSessionCurrent();
    if (loggedIn && sessionCurrent) {
      return true;
    }

    if (loggedIn && !sessionCurrent) {
      this.userService.clearCurrentUserAndToken();
      this.alertService.error('Your session has expired.', true);
    }

    if (url && url.charAt(0) !== '/') {
      url = '/' + url;
    }
    this.authService.setLoginReturnUrl(url);

    this.authService.startAuthentication();
    return false;
  }
}

共1个答案

匿名用户

将PublicKeyService添加到应用程序模块的提供者,如下所示:

@NgModule({
  imports:      [ BrowserModule ],
  providers:    [ PublicKeyService ],
  declarations: [ AppComponent ],
  exports:      [ AppComponent ],
  bootstrap:    [ AppComponent ]
})
export class AppModule { }

您在"Authation-secure-auth-service"中注入了public KeyService,因此您应该将getClientSettings()函数作为公共方法移动到您的"Authation-secure-auth-service"类主体中,而不是将您声明的"导出函数"移出设置类主体!

您可以像这样更改您的方法并在需要的地方订阅其结果:

public getClientSettings() {
 return  this.publicKeyService.getClientSettings(); 
}

但实际上你似乎不需要这个改变。根据您的评论,在您的AuthenticationSecureAuthService构造函数中尝试以下更改:

替换这部分代码:

 this.manager = new UserManager(getClientSettings());  
 this.start();

有了这个:

  this.publicKeyService.getClientSettings().subscribe(
      data =>{   
         this.manager = new UserManager(data);
         this.start();
    }
  );