this.user 在 angular -oidc-client 中从 app.component 获取数据时未定义

this.user is undefined when fetch data from app.component in angular -oidc-client

我在我的 angular 项目中使用 oidc-client.js

现在用户可以登录和注销并且工作正常。唯一的问题是,当我想在 app.component 中调用服务时,在拦截器中用户未通过身份验证。

auth.service 是:

    Injectable({
  providedIn: 'root'
})
export class AuthService extends BaseService {


  private _authNavStatusSource = new BehaviorSubject<boolean>(false);

  authNavStatus$ = this._authNavStatusSource.asObservable();

  private manager = new UserManager(getClientSettings());
  private user: User | null;


  constructor(private http: HttpClient) {
    super();   
    this.manager.getUser().then(user => {
      this.user = user;
      this._authNavStatusSource.next(this.isAuthenticated());
    });
  }

  login() {
    return this.manager.signinRedirect();
  }

  async completeAuthentication() {
    this.user = await this.manager.signinRedirectCallback();
    this._authNavStatusSource.next(this.isAuthenticated());
  }


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

  get authorizationHeaderValue(): string {
    return `${this.user.token_type} ${this.user.access_token}`;
  }

  async signout() {
    await this.manager.signoutRedirect();
  }
}

export function getClientSettings(): UserManagerSettings {
  return {
    authority:environment.authApiURI,
    client_id: 'medilloxdashboard',
    redirect_uri: environment.redirect_uri,
    post_logout_redirect_uri: environment.postLogoutRedirectUri,
    response_type: "id_token token",
    scope: "openid spa profile",
    filterProtocolClaims: true,
    loadUserInfo: true,
    automaticSilentRenew: true,
    silent_redirect_uri:environment.silentRedirectUri,
    userStore: new WebStorageStateStore({ store: localStorage })
  };
}

我写了一个拦截器来为所有请求添加令牌,如下所示:

@Injectable()
export class AuthInterceptor implements HttpInterceptor {
  private authorizationHeader = "Authorization";

  constructor(
    private authService: AuthService,
    private router: Router) { }
  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    request = request.clone({
      headers: request.headers.set(this.authorizationHeader, this.authService.authorizationHeaderValue)
    });
    return next.handle(request);
  }

}

AuthServiceAuthInterceptor 注册在 Core nodule.

App.Compoentn 中,我调用了这样的服务,它调用了 REST api

    export class AppComponent implements OnInit {

  title = 'myapp';
  version: string;

     constructor(
        private router: Router,
        private dashboardService: DashboardService) {
        this.version = environment.version;
      }
    
      ngOnInit(): void {
        this.dashboardService.getDashboards().subscribe();
      }
    }

当这个调用发生时,我得到 getDashboards failed: this.user is undefined 但我在另一个组件中调用了这个服务,它工作正常。

components which call this service and get the result are in their modules.

问题出在哪里?

尝试在内部拨打电话 ngAfterViewCheck 而不是 ngOnInit 因为此时服务尚未启动。小心会被无限执行。您可以继续拨打电话,而用户未定义。

回答你的问题 @osman Rahimi“在 ngAfterViewChecked 中没问题,但是每当我点击每个按钮时,这段代码 运行。有没有更好的方法? “

答案:

  data: any;
  ngAfterViewChecked (): void {
    if(this.data === null || this.data === undefined) {
      this.dashboardService.getDashboards().subscribe(data => this.data = data);
    }
  }

我创建了一个这样的Initializer

import { AuthService } from "./auth-service";
export function AuthInitializer(auth: AuthService) { return () => auth.isAuthenticated() };

并在 core.module

中这样注册
providers: [

{
  provide: APP_INITIALIZER,
  useFactory: AuthInitializer,
  deps: [AuthService],
  multi: true
}]

这是完美的工作。