web-dev-qa-db-ja.com

「AuthGuardのプロバイダーはありません!」 Angular 2でCanActivateを使用

EDIT:これは明らかに時代遅れです。NgModuleのproviders配列でガードを提供するようになりました。詳細については、他の回答または公式ドキュメントをご覧ください。

  • コンポーネントのブートストラップは古くなっています
  • provideRouter()も古くなっています


Angular2ガイドのログインとAuthGuardを使用して、プロジェクトで認証を設定しようとしています: https://angular.io/docs/ts/latest/guide/router.html

リリースを使用しています: "@ angular/router": "3.0.0-beta.1"。

できる限り説明するようにしますが、詳細が必要な場合はお気軽にお知らせください。


次のコードでアプリをブーストするmain.tsファイルがあります:

bootstrap(MasterComponent, [
    APP_ROUTER_PROVIDERS,
    MenuService
])
.catch(err => console.error(err));

MasterComponentをロードします。これは、アプリをナビゲートするためのボタンを含むヘッダーをロードし、現在はメインも含まれています。

次のapp.routes.tsを使用して、アプリを同じように動作させるためのガイドに従っています:

export const routes: RouterConfig = [
    ...LoginRoutes,
    ...MasterRoutes
];

export const APP_ROUTER_PROVIDERS = [
    provideRouter(routes),
    AUTH_PROVIDERS
];

そして、AuthGuardを定義するガイドのlogin.routes.ts

export const LoginRoutes = [
    { path: 'login', component: LoginComponent }
];

export const AUTH_PROVIDERS = [AuthGuard, AuthService];

マスターコンポーネントには独自のルート定義があり、これにはセットアップしようとしているガードも含まれています。 master.routes.ts

export const MasterRoutes : RouterConfig = [
    { path: '', redirectTo: '/accueil', pathMatch: 'full' },

    {
        path: 'accueil',
        component: AccueilComponent
    },

    { path: 'dashboard', component: DashboardComponent, canActivate: [AuthGuard] },
];

そして、ガイドと同じファイルを使用しています。auth.guard.tsauth.service .tslogin.component.tsおよびlogin.routes.ts


私のheader.component.tsファイルでは、ルートにアクセスしようとするとうまく機能しますが、保護されたパスにアクセスしようとすると(/dashboard)、AuthGuardのプロバイダーがありません!エラーが表示されます。

私と同じ問題の最近の投稿を見ました( Angular 2 でCanActivateを使用するNoProviderError)が、私にとってはガードはmain.tsファイルなので、ルーターはどのルートにAuthGuard権限を提供する必要があるかを知る必要がありますか?

どんな助けやアドバイスも大歓迎です。ありがとう!

28
Alex Beugnet

実際、それはインポートのタイプミスにすぎませんでした...

入力していた

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

の代わりに

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

動作しませんが、同時にエラーが表示されません...

(悲しい顔)

5
Alex Beugnet

Angularウェブサイト https://angular.io/docs/ts/latest/guide/のルーティングと承認のチュートリアルのルートガードセクションを通過した後、この同じ問題がありました。 router.html 、セクション5です。

チュートリアルショーのような子ルートではなく、メインルートの1つにAuthGuardを追加しています。

App.module.tsファイルのプロバイダーのリストにAuthGuardを追加することで修正しました。このファイルは次のようになります。

import { AppComponent } from './app.component';
import {AppRoutingModule} from './app-routing.module';
import {AuthGuard} from './auth-gaurd.service';

import { AnotherPageComponent } from './another-page/another-page.component';
import { LoginPageComponent } from './login-page/login-page.component';

@NgModule({
  imports: [
    BrowserModule,
    FormsModule,
    JsonpModule,
    AppRoutingModule,
    HttpModule
  ],
  declarations: [
    AppComponent,
    LoginPageComponent,
    AnotherPageComponent
  ],
  providers: [AuthGuard],
  bootstrap: [AppComponent]
})

export class AppModule { }

私はチュートリアルを繰り返しましたが、app.module.tsファイルでは、プロバイダーにAuthGuardを追加していません。理由はわかりません。

60

また、いくつかのブログ記事がそうしているという理由だけで、ルーティング構成内でガードクラスにリテラルを使用するというtrapに陥らないでください。

{ path: 'whatever', component: WhatEverComponent, canActivate: ['WhatEverGuard'] }

動作しません(No provider for...)代わりに、クラスを直接使用します。

{ path: 'whatever', component: WhatEverComponent, canActivate: [WhatEverGuard] }

別のヒントとして、コンポーネントを遅延読み込みする場合、ガードは遅延読み込みコンポーネントのルーティング構成ではなく、親コンポーネントのルーティング構成に適用されます。

15

まだこのエラーが発生する場合は、AuthGuardサービスまたはクラスをmain bootstrap= function。に含めることを忘れないでください。また、bootstrap実行します。

import { bootstrap } from '@angular/platform-browser-dynamic';

import { AppComponent } from './app.component';
import { AuthGuard } from './shared/auth.service';

bootstrap(AppComponent, [
  appRouterProviders,
  AuthGuard
]);

Angular 2チームは、メインルーターのドキュメントでこれについて言及していませんでした。

11
Roman Gusiev

答えはチュートリアルのさらに下にあります。 「Milestone 5:Route Guards」の「Component-less route:...」セクションの下にある「Add the LoginComponent」トピックのファイルリストを参照してください。 AuthGuardとAuthServiceがインポートされ、login-routing.module.tsのプロバイダー配列に追加され、そのモジュールがapp.module.tsにインポートされていることが示されています。

login-routing.module.ts

  ...
    import { AuthGuard }            from './auth-guard.service';
    import { AuthService }          from './auth.service';
    ...
    @NgModule({
    ...
      providers: [
        AuthGuard,
        AuthService
      ]
    })
    export class LoginRoutingModule {}

app.module.ts

import { LoginRoutingModule }      from './login-routing.module';

@NgModule({
  imports: [
    ...
    LoginRoutingModule,
    ...    
  ],
  ...
  providers: [
    DialogService
  ],
  ...
7
unqualified

この問題は、チュートリアルに従っているときに発生しました。ここでほとんどの答えを試しましたが、成功しませんでした。次に、プロバイダ内の他のサービスの前にAuthGuardを置くなどのばかげた方法を試しましたが、動作します。

// app.module.ts

 .. 
 providers: [
   AuthGuard,
   UserService,
   ProjectService
  ]
3
import { Injectable } from '@angular/core';
import { Router, CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';

@Injectable()
export class AuthGuard implements CanActivate {

    constructor(private router: Router) { }

    canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
        if (localStorage.getItem('currentUser')) {
            // logged in so return true
            return true;
        }

        // not logged in so redirect to login page with the return url
        this.router.navigate(['/login'], { queryParams: { returnUrl: state.url }});
        return false;
    }
}
1
Shailesh kala

追加してみてください

@Injectable({ providedIn: 'root' })モジュールプロバイダーに追加する必要はありません。

1
Ryan Huang

構文の問題が原因で解決策を得たからです。この情報を共有したかっただけです。

それぞれのルートに対応するモジュールでのみ、AuthGaudSerivceをプロバイダーとして提供する必要があります。メインモジュールは指定されたすべてのサブモジュールを自動的にロードするため、メインモジュールまたはルートモジュールを提供する必要はありません。これにより、コードをモジュール化してカプセル化できます。

たとえば、次のシナリオがあるとします

1. we have module m1
2. we have route m1r in module m1
3. route m1r has 2 route r1 and r2
4. we want to protect r1 using authGaurd
5. finally we have main module that is dependent on sub module m1 

以下はプロトタイプであり、目的を理解するための実際のコードではありません

//m1.ts    
import {AuthGaurd} from './auth.gaurd.service'
import {m1r} from './m1r'
    @NgModule(
     imports: [m1r],
     providers: [AuthGaurd]
    )
    export class m1{
    }

//m1r.ts
import {AuthGaurd} from './auth.gaurd.service'
const authRoute = [
 {path: '/r1', component: 'authComponent', canActivate: [AuthGaurd]},
 {path: '/r2', component: 'other'}
]
export authRoute

//main.module.ts
import {m1} from ''
import {mainComponent} from ''
@NgModule({
  imports: [m1],
  bootstrap: [mainComponent]
  })
export class MainModule{}    
1
Vikash

HttpModuleHttpClientModuleの両方をインポートすると助けになりました。

import { HttpClientModule } from '@angular/common/http'; 
import { HttpModule } from '@angular/http';
1
Ramya

そのモジュールのプロバイダーにAuthGuardをインポートしてから、ルーティングコンポーネントのrouting.module.tsファイルにもインポートできます。

@NgModule({
providers: [
    AuthGuard
  ],})