我想利用的角度,智威汤逊 ,但我得到了跟随循环依赖错误:
Cannot instantiate cyclic dependency! InjectionToken_JWT_OPTIONS
at NgModuleProviderAnalyzer.parse (compiler.js:19550)
at NgModuleCompiler.compile (compiler.js:20139)
at JitCompiler._compileModule (compiler.js:34437)
at eval (compiler.js:34368)
at Object.then (compiler.js:474)
at JitCompiler._compileModuleAndComponents (compiler.js:34366)
at JitCompiler.compileModuleAsync (compiler.js:34260)
at CompilerImpl.compileModuleAsync (platform-browser-dynamic.js:239)
at PlatformRef.bootstrapModule (core.js:5567)
at eval (main.ts:13)
在我的第一个演示角5的应用,这里是我的设置:
import {NgModule} from '@angular/core';
import {HttpClientModule} from '@angular/common/http';
import {JwtModule, JWT_OPTIONS} from '@auth0/angular-jwt';
import {KeycloakService} from './keycloak.service';
// See https://github.com/auth0/angular2-jwt
export function jwtOptionsFactory(keycloakService) {
return {
whitelistedDomains: ['localhost:3001'],
blacklistedRoutes: ['localhost:3001/auth/'],
tokenGetter: () => {
return keycloakService.getJwtTokenFromLocalStorage();
}
};
}
@NgModule({
imports: [
HttpClientModule,
JwtModule.forRoot({
jwtOptionsProvider: {
provide: JWT_OPTIONS,
useFactory: jwtOptionsFactory,
deps: [KeycloakService]
}
})
],
providers: [
KeycloakService
]
})
export class AuthModule {}
有一个空DEPS:属性删除问题。 当然,没有被注入的服务是没有解决办法。
我的服务是:
import {Injectable} from '@angular/core';
import {environment} from '../environments/environment';
import {Observable} from 'rxjs';
import {JwtHelperService} from '@auth0/angular-jwt';
import {HttpClient, HttpHeaders} from '@angular/common/http';
declare let Keycloak: any;
const JWT_TOKEN_NAME: string = 'token';
@Injectable()
export class KeycloakService {
static auth: any = {};
constructor(private httpClient: HttpClient, private jwtHelperService: JwtHelperService) {}
static init(): Promise<any> {
const keycloakAuth: any = Keycloak({
url: environment.KEYCLOAK_URL,
realm: environment.KEYCLOAK_REALM,
clientId: environment.KEYCLOAK_CLIENTID,
'ssl-required': 'external',
'public-client': true
});
KeycloakService.auth.loggedIn = false;
return new Promise((resolve, reject) => {
keycloakAuth.init({onLoad: 'check-sso'})
.success(() => {
console.log('The keycloak client has been initiated successfully');
KeycloakService.auth.loggedIn = true;
KeycloakService.auth.authz = keycloakAuth;
KeycloakService.auth.logoutUrl = environment.KEYCLOAK_URL
+ '/realms/' + environment.KEYCLOAK_REALM + '/protocol/openid-connect/logout?redirect_uri='
+ document.baseURI;
resolve();
})
.error(() => {
reject();
});
});
}
static hasRole(role: string): boolean {
return KeycloakService.auth.authz.tokenParsed.realm_access.roles.indexOf(role) > -1;
}
static getUsername(): string {
return KeycloakService.auth.authz.tokenParsed.preferred_username;
}
static getFullName(): string {
return KeycloakService.auth.authz.tokenParsed.name;
}
public login(ussername: string, password: string): Observable<any> {
console.log('Sending the login credentials to obtain a token');
const credentials = {username: ussername, password: password};
const url: string = environment.KEYCLOAK_URL + '/realms/' + environment.KEYCLOAK_REALM
+ '/protocol/openid-connect/token/generate-token';
return this.httpClient.post(url, credentials);
}
public logout(): void {
KeycloakService.auth.loggedIn = false;
KeycloakService.auth.authz = null;
window.location.href = KeycloakService.auth.logoutUrl;
}
public getToken(): Promise<string> {
return new Promise<string>((resolve, reject) => {
if (KeycloakService.auth.authz && KeycloakService.auth.authz.token) {
KeycloakService.auth.authz
.updateToken(5) // Refresh the token if it will expire in n seconds or less
.success(() => {
resolve(<string>KeycloakService.auth.authz.token);
})
.error(() => {
reject('Failed to refresh the auth token');
});
} else {
reject('The auth token could not be retrieved because the user was not logged in');
}
});
}
public isAuthenticated(): boolean {
const token = this.getJwtTokenFromLocalStorage();
return (token && !this.jwtHelperService.isTokenExpired(token));
}
public getTokenExpirationDate() {
const token = this.getJwtTokenFromLocalStorage();
return this.jwtHelperService.getTokenExpirationDate(token);
}
public getDecodedToken() {
const token = this.getJwtTokenFromLocalStorage();
return this.jwtHelperService.decodeToken(token);
}
public getJwtTokenFromLocalStorage(): string {
return localStorage.getItem(JWT_TOKEN_NAME);
}
public setJwtTokenToLocalStorage(token: string): void {
localStorage.setItem(JWT_TOKEN_NAME, token);
}
public getJwtTokenName(): string {
return JWT_TOKEN_NAME;
}
}
我所有的依赖关系是:
"@angular/animations": "^5.2.0",
"@angular/common": "^5.2.0",
"@angular/compiler": "^5.2.0",
"@angular/core": "^5.2.0",
"@angular/forms": "^5.2.0",
"@angular/http": "^5.2.0",
"@angular/platform-browser": "^5.2.0",
"@angular/platform-browser-dynamic": "^5.2.0",
"@angular/router": "^5.2.0",
"@auth0/angular-jwt": "^1.0.0",
"angular-in-memory-web-api": "^0.5.3",
"core-js": "^2.4.1",
"jwt-decode": "^2.2.0",
"keycloak-js": "^3.4.3",
"npm": "^5.6.0",
"rxjs": "^5.5.6",
"zone.js": "^0.8.19"
更新:我来拆分业务分成两个服务,一个KeycloakService
对付Keycloak
服务器和AuthService
排序它封装的,从而具有更小尺寸的服务。 问题仍然虽然,我不得不去为大卫的解决方案,他所提到的解决方法。 而我的新AuthService
具有下面的构造:
@Injectable()
export class AuthService {
// constructor(private jwtHelperService: JwtHelperService) {} TODO
jwtHelperService: JwtHelperService;
constructor(private injector: Injector) {
let jwtHelperService = this.injector.get(JwtHelperService);
}