2016-12-30 40 views
7

Próbuję zaimplementować funkcję auth guard w mojej aplikacji. to znaczy; Tylko uwierzytelnieni użytkownicy mają dostęp do niektórych tras mojej aplikacji. Podążam za tutorem podanym here.Jak utworzyć singleton Angular2 Service?

Po zalogowaniu użytkownika zmieniaję wartość logiczną w moim AuthService na wartość true, aby wskazać, że logowanie się zalogowało. Którą należy zachować przez cały okres eksploatacji aplikacji.

Biorąc pod kodem źródłowym:

auth-guard.service.ts

import { Injectable }  from '@angular/core'; 
import { 
    CanActivate, Router, 
    ActivatedRouteSnapshot, 
    RouterStateSnapshot 
}      from '@angular/router'; 
import { AuthService } from './auth.service'; 

@Injectable() 
export class AuthGuardService implements CanActivate { 
    constructor(private authService: AuthService, private router: Router) {} 
    canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {   
    let url: string = state.url; 
    return this.checkLogin(url); 
    } 

    checkLogin(url: string): boolean { 
    console.log('Auth Guard Service: ' + this.authService.isLoggedIn); 
    if (this.authService.isLoggedIn) { return true; } 
    // Store the attempted URL for redirecting 
    this.authService.redirectUrl = url; 

    // Navigate to the login page with extras 
    this.router.navigate(['/admin', 'admin-login']); 
    return false; 
    } 
} 

auth.service.ts

import { Injectable } from '@angular/core'; 
    import { Http } from '@angular/http'; 

    import { User } from '../user/shared/user.model'; 

    import { ServiceBase } from '../../core/service.base'; 
    import { appConfig } from '../../core/app.config'; 

    @Injectable() 
    export class AuthService extends ServiceBase { 
     public isLoggedIn: boolean = false; 
     redirectUrl: string; 
     apiUrl: string; 
     constructor(private http: Http) { 
      super(); 
      this.apiUrl = appConfig.apiBaseUrl + '/users/signin'; 
     } 
     signin(user: User, successCallback, errorCallback) { 
      return this.http.post(this.apiUrl, user).subscribe(
       res => { 
        this.isLoggedIn = true; 
        successCallback(res); 
       }, 
       err => { 
        //this.isLoggedIn = false; 
        errorCallback(err); 
       } 
      ); 
     }    
    } 

login.component.ts

import { Component, OnInit } from '@angular/core'; 
import { FormGroup, FormBuilder, FormControl, Validators } from '@angular/forms'; 
import { Router } from '@angular/router'; 
import { User } from '../../user/shared/user.model'; 
import { AuthService } from '../auth.service'; 

@Component({ 
    moduleId: module.id, 
    templateUrl: 'login.component.html' 
}) 
export class AdminLoginComponent implements OnInit{ 

    user: User; 
    userLoginForm: FormGroup; 

    constructor(
     private formBuilder: FormBuilder, 
     private authService: AuthService, 
     private router: Router){ 
     this.user = new User(); 
    } 

    ngOnInit(){ 
     this.buildLoginForm(); 
    } 
    buildLoginForm() { 
     ... 
    } 
    login() { 
     if(!this.userLoginForm.valid) return false; 
     this.authService.signin(this.user, 
      response => { 
       console.log('Login Component: ' + this.authService.isLoggedIn); 
       this.router.navigate(['/admin', 'products']); 
      }, 
      response => {} 
     ); 
    } 
} 

wyjście Console

XHR finished loading: POST "http://localhost:3000/api/users/signin". 
login.component.ts:40 Login Component: true 
auth-guard.service.ts:23 Auth Guard Service: false 

Edit: app.module.ts

import { NgModule } from '@angular/core'; 
    ... 
    import { AuthGuardService } from './auth/auth-guard.service'; 
    import { AuthService } from './auth/auth.service'; 

    @NgModule({ 
     imports: [ 
      ... 
      AdminRoutingModule 
     ], 
     exports: [ 
     ], 
     declarations: [ 
      ... 
      AdminLoginComponent, 
      ... 
     ], 
     providers: [ 
      AuthGuardService, 
      AuthService, 
      ... 
     ], 
     bootstrap:[] 
    }) 
    export class AdminModule {} 

Co robię źle tutaj? Każda pomoc będzie doceniona.

+2

aby usługa singleton trzeba dodać wszystkie usługi wewnątrz 'sekcji providers' swojego' modules'. Jeśli dodałeś usługi w sekcji 'provider' twojego komponentu, to dla tego komponentu zostanie zainicjowana nowa instancja usługi. – ranakrunal9

+0

Pokaż nam, gdzie zostały dodane te usługi? App.module – Milad

Odpowiedz

3

Jak wspomniano przez ranakrunal9, jeśli udostępniasz usługę na komponencie lub dyrektywie, otrzymujesz nową instancję dla każdej instancji takiego komponentu.

Otrzymujesz również nowe wystąpienie dla leniwych modułów ładowanych (załadowanych loadChildren). Lazy ładowane moduły mają swój własny zakres główny, a komponenty i usługi w tym module otrzymają inne wystąpienie usługi wstrzykniętej, jeśli ta usługa jest zapewniona w tym leniwym załadowanym module.

Aby upewnić się, że masz tylko jedną instancję dla całej aplikacji, podaj ją tylko w swoim AppModule lub module załadowanym przez AppModule bezpośrednio lub pośrednio przy użyciu imports: [...].

Zobacz także https://stackoverflow.com/a/40981772/217408

+1

Podałem 'AuthService' w moim podmodule (Moduł administracyjny). Jak zasugerowałeś, podałem 'AuthService' w' AppModule', teraz wszystko działa dobrze. Dziękuję Ci! –

+0

Nie ma za co. Cieszę się, że możesz to sprawić. –