NullInjectorError: No provider for JwtHelperService

NullInjectorError: No provider for JwtHelperService

我在 Angular 5.

第一个:npm install @auth0/angular-jwt --save

然后我导入它:import { JwtHelperService } from '@auth0/angular-jwt';

这是我的身份验证服务:

import { JwtHelperService } from '@auth0/angular-jwt';

@Injectable()
export class AuthService {

  constructor(public jwtHelper: JwtHelperService) { }

  public isAuthenticated(): boolean {
    console.log (localStorage['token']);
    const token = localStorage.getItem('token');
    // Check wheter the token is expired and return true or false
    return !this.jwtHelper.isTokenExpired(token);
  }
}

这是我的 Guard 服务

export class GuardService implements CanActivate {

  constructor(public auth: AuthService, public router: Router) {}

  canActivate(): boolean {
    if (!this.auth.isAuthenticated()){
        console.log ('bye');
        this.router.navigate(['/login']);
        return false;
    }
    console.log ('Welcome');
    return true;
  }

}

localstorage中有token:

eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImp0aSI6ImFjMTUyNzZhZjA2MjU1YTdlMDM0MmQ5ODg4N2M1ZmI2ZWNmM2RlNGUyNjhmYTc4MTliODRhOTVmMmJiNGZiMTliMDFkNjBhNWRlNjhlN2VlIn0.eyJhdWQiOiJmMDExY2M1OC00MGNlLTQzYTktOGY3MS04NDI0OTRlM2E5OTciLCJqdGkiOiJhYzE1Mjc2YWYwNjI1NWE3ZTAzNDJkOTg4ODdjNWZiNmVjZjNkZTRlMjY4ZmE3ODE5Yjg0YTk1ZjJiYjRmYjE5YjAxZDYwYTVkZTY4ZTdlZSIsImlhdCI6MTUyMzI5NzkzNSwibmJmIjoxNTIzMjk3OTM1LCJleHAiOjE1MjMyOTgyMzUsInN1YiI6IjIiLCJzY29wZXMiOlsiYXV0aGVudGljYXRlZCIsImFuZ3VkcnUiXX0.RNY2Yb9xiJDcER4rtHEAYMmoLyvPYij-upZc97q-mSgICKE6_xWih_IBjY4cHQXkkiRyCXaqCfwfMM4YWVjv7bsMlLN5bWlH0JTeYoYf2gENLBIG51NwGpU3iAl8KG_51ljZKbs3RE_ULDbphM1NG8BhobVQ5RlObWzejrkPcMHqlGJaMOMLQuXC1iBR2jI9tlfiP4RD4FUUsRkUEUJ5PSIRl34jWoTv31SSf1bkv43q3YeKTfk6pXZ5Ft_eV8G871KkmQSHANAn26A5ujj2FOh-uCV_VNJ97RuTQ6J4NP2YB-mMaWYpZ1xF-4ndqafRGFXJ_8euBO4cA36zvP3B7g

这是错误:

ERROR Error: Uncaught (in promise): Error: StaticInjectorError(AppModule)[AuthService -> JwtHelperService]: 
  StaticInjectorError(Platform: core)[AuthService -> JwtHelperService]: 
    NullInjectorError: No provider for JwtHelperService!
Error: StaticInjectorError(AppModule)[AuthService -> JwtHelperService]: 
  StaticInjectorError(Platform: core)[AuthService -> JwtHelperService]: 
    NullInjectorError: No provider for JwtHelperService!
    at _NullInjector.get (core.js:1002)
    at resolveToken (core.js:1300)
    at tryResolveToken (core.js:1242)
    at StaticInjector.get (core.js:1110)
    at resolveToken (core.js:1300)
    at tryResolveToken (core.js:1242)
    at StaticInjector.get (core.js:1110)
    at resolveNgModuleDep (core.js:10854)
    at _createClass (core.js:10891)
    at _createProviderInstance (core.js:10865)
    at _NullInjector.get (core.js:1002)
    at resolveToken (core.js:1300)
    at tryResolveToken (core.js:1242)
    at StaticInjector.get (core.js:1110)
    at resolveToken (core.js:1300)
    at tryResolveToken (core.js:1242)
    at StaticInjector.get (core.js:1110)
    at resolveNgModuleDep (core.js:10854)
    at _createClass (core.js:10891)
    at _createProviderInstance (core.js:10865)
    at resolvePromise (zone.js:814)
    at resolvePromise (zone.js:771)
    at eval (zone.js:873)
    at ZoneDelegate.invokeTask (zone.js:421)
    at Object.onInvokeTask (core.js:4740)
    at ZoneDelegate.invokeTask (zone.js:420)
    at Zone.runTask (zone.js:188)
    at drainMicroTaskQueue (zone.js:595)

此外,它向我显示了路线,但没有来自服务的数组...

您需要使用@auth0/angular-jwt提供的JwtModule,它将JwtHelperService添加到提供者中,或者您需要手动将其添加到模块提供者中。

类似

const JWT_Module_Options: JwtModuleOptions = {
    config: {
        tokenGetter: yourTokenGetter,
        whitelistedDomains: yourWhitelistedDomains
    }
};

@NgModule({
    imports: [
        JwtModule.forRoot(JWT_Module_Options)
    ],
...

更多见Documentation

为了将来参考,如果您只想使用 JwtHelper 进行解码,例如在本例中检查令牌是否过期,那么您可以使用它。

import { JwtHelperService } from '@auth0/angular-jwt';

const jwtHelper = new JwtHelperService();

@Injectable()
export class AuthService {
    public isAuthenticated(): boolean {
    const token = localStorage.getItem('token');

    // Check if the token is expired and return true or false
    return !this.jwtHelper.isTokenExpired(token);
}

来源:Documentation

晚会有点晚了,但我 运行 遇到了同样的问题,试图遵循独立文档,但它没有涵盖的是需要导入在构造函数中引用的选项 InjectionToken服务:

import { JwtHelperService, JWT_OPTIONS  } from '@auth0/angular-jwt';

...

providers: [
        { provide: JWT_OPTIONS, useValue: JWT_OPTIONS },
        JwtHelperService
    ]

我通过更改我的导入解决了这个问题:

import { JwtHelperService } from '@auth0/angular-jwt';

import { JwtHelperService } from '@auth0/angular-jwt/src/jwthelper.service';

对我有用的最简单的解决方案是声明“JwtHelperService”的常量变量类型,而不是在构造函数中声明它。

 const helper = new JwtHelperService ();

现在使用带有助手常量的助手服务

 return !helper.isTokenExpired(token);

出现这个问题是因为您没有在 app.module.ts

的导入中添加 JWT 模块
export function tokenGetter() {
  return localStorage.getItem("access_token");
}

JwtModule.forRoot({
      config: {
        tokenGetter: tokenGetter,
        allowedDomains: ["example.com"],
        disallowedRoutes: ["http://example.com/examplebadroute/"],
      },
    }),

如果您使用 @auth0/angular-jwt 获取 jwt 帮助并使用依赖注入访问模块,则有必要将 jwt 模块导入 app.module.ts 或者你的模块是什么 used.moreover 你有更多的权限来配置你的模块导入器,包括不允许的域、允许的域、header 名称、自定义工厂函数等

import { JwtModule } from "@auth0/angular-jwt";
import { HttpClientModule } from "@angular/common/http";

export function tokenGetter() {
  return localStorage.getItem("access_token");
}

@NgModule({
  bootstrap: [AppComponent],
  imports: [
    // ...
    HttpClientModule,
    JwtModule.forRoot({
      config: {
       tokenGetter: tokenGetter,
      allowedDomains: ["localhost:3001", "foo.com", "bar.com"]
      },
    }),
  ],
})
export class AppModule {}

如果不想注入,可以实例化。

import { JwtHelperService } from "@auth0/angular-jwt";

const helper = new JwtHelperService();

const decodedToken = helper.decodeToken(myRawToken);
const expirationDate = helper.getTokenExpirationDate(myRawToken);
const isExpired = helper.isTokenExpired(myRawToken); 

我也遇到过这个问题。我找到了解决方法:

测试配置

在您的 modulename.spec.ts 中,确保为 JwtHelperService 配置提供程序(在我的例子中是 AuthGuard.spec.ts):


import { TestBed, inject, waitForAsync } from '@angular/core/testing';
import { RouterTestingModule } from "@angular/router/testing";
import { HttpTestingController, HttpClientTestingModule } from '@angular/common/http/testing';
import { JwtModule, JwtHelperService } from '@auth0/angular-jwt';

import { AuthGuard } from './auth.guard';

let jwtHelper: JwtHelperService;
const testBedConfiguration = {
  imports: [
    RouterTestingModule.withRoutes([]),
    HttpClientTestingModule,
    JwtModule.forRoot({ // for JwtHelperService
      config: {
        tokenGetter: () => {
          return '';
        }
      }
    })
  ],
  providers: [
    AuthGuard,
    JwtHelperService
  ]
}

describe('AuthGuard', () => {
  beforeEach(() => {
    TestBed.configureTestingModule(testBedConfiguration);
    jwtHelper = TestBed.get(JwtHelperService);
  });

  it('should ...', inject([AuthGuard], (guard: AuthGuard) => {
    expect(guard).toBeTruthy();
  }));
});

这解决了我的问题,但由于我的实现是在我的 authguard 用于路由的 auth 服务中,我必须在我受 authguard 保护的每个页面中包含该配置。

import { JwtModule, JwtHelperService } from '@auth0/angular-jwt';

public jwtHelper: JwtHelperService = new JwtHelperService();

constructor(
private http: Http,
) { }
     decodeToken() {
         const token = localStorage.getItem('token');
         return this.jwtHelper.decodeToken(token);
     }

这解决了我的问题 https://github.com/auth0/angular2-jwt/issues/482#issuecomment-569251938