【问题标题】:NullInjectorError: No provider for JwtHelperServiceNullInjectorError:没有 JwtHelperService 的提供者
【发布时间】:2018-09-19 05:25:21
【问题描述】:

我在 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$1 (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$1 (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)

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

【问题讨论】:

    标签: json angular typescript jwt guard


    【解决方案1】:

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

    import { JwtHelperService, JWT_OPTIONS  } from '@auth0/angular-jwt';
    
    ...
    
    providers: [
            { provide: JWT_OPTIONS, useValue: JWT_OPTIONS },
            JwtHelperService
        ]
    

    【讨论】:

    • 这些会进入app.module.ts吗?
    • 我认为这应该是正确的答案。
    【解决方案2】:

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

    类似

    const JWT_Module_Options: JwtModuleOptions = {
        config: {
            tokenGetter: yourTokenGetter,
            whitelistedDomains: yourWhitelistedDomains
        }
    };
    
    @NgModule({
        imports: [
            JwtModule.forRoot(JWT_Module_Options)
        ],
    ...
    

    更多内容见Documentation

    【讨论】:

    • 是的,最好在顶层模块中使用
    【解决方案3】:

    为了将来参考,如果您只想使用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

    【讨论】:

      【解决方案4】:

      出现这个问题是因为你没有在 app.module.ts 中的导入中添加 JWTmodule

      export function tokenGetter() {
        return localStorage.getItem("access_token");
      }
      
      JwtModule.forRoot({
            config: {
              tokenGetter: tokenGetter,
              allowedDomains: ["example.com"],
              disallowedRoutes: ["http://example.com/examplebadroute/"],
            },
          }),
      

      【讨论】:

        【解决方案5】:

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

         const helper = new JwtHelperService ();
        

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

         return !helper.isTokenExpired(token);
        

        【讨论】:

          【解决方案6】:

          如果您使用 @auth0/angular-jwt 来获得 jwt 帮助并使用依赖注入来访问模块,则有必要将 jwt 模块导入 app.module.ts 或任何其他您使用的模块。此外,您有更多权限来配置模块导入器,包括不允许的域、允许的域、标头名称、自定义工厂函数等。

          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); 
          

          【讨论】:

            【解决方案7】:

            我也在与这个问题作斗争。我找到了解决方法:

            测试配置

            在您的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 用于路由的身份验证服务中,因此我必须在我受 authguard 保护的每个页面中包含该配置。

            【讨论】:

              【解决方案8】:

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

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

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

              【讨论】:

              • 这是一个非标准的,因此不推荐的做法
              猜你喜欢
              • 2019-11-16
              • 2021-01-20
              • 2019-06-25
              • 2018-05-02
              • 2020-12-25
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多