简体   繁体   中英

Angular 2 Organize AuthGuard(canActivate) and AuthService code

From my current code, when routing to a page with canActivate, I am able to achieve the authentication data from the server with the below

auth.guard.ts (version 1)

import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, Router } from '@angular/router';
import { Observable } from 'rxjs/Rx';
import { Injectable } from '@angular/core';
import { Http } from '@angular/http';
import { Headers, RequestOptions } from '@angular/http';

@Injectable()
export class AuthGuard implements CanActivate {
    constructor(private router: Router, private http: Http) { }

    canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
        let headers = new Headers({ 'Content-Type': 'application/json' });
        let options = new RequestOptions({ headers: headers });

        return this.http.post('/api/authenticate', options )
            .map(res => res.json())
            .map((res) => {
                if (res.response) {
                    return true;
                } else {
                    this.router.navigate(['/register']);
                    return false;
                }
            });
    }
}

I would want to to separate the code inside canActivate to auth.service.ts as below, but it is does not wait for the http request to finish and return

auth.service.ts

import { Injectable } from '@angular/core';
import { Http } from '@angular/http';
import { Headers, RequestOptions } from '@angular/http';
import 'rxjs/add/operator/map';
import { Observable } from 'rxjs/Observable';

@Injectable()
export class AuthService {
    constructor(private http: Http) { }

    authenticate() :Observable<any>{
        let headers = new Headers({ 'Content-Type': 'application/json' });
        let options = new RequestOptions({ headers: headers });

        return this.http.post('/api/authenticate', { options })
            .map(res => res.json())
    }
}

auth.guard.ts (version 2)

    import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, Router } from '@angular/router';
import { Observable } from 'rxjs/Rx';
import { Injectable } from '@angular/core';
import { Http } from '@angular/http';
import { Headers, RequestOptions } from '@angular/http';
import { AuthService } from './auth.service';

@Injectable()
export class AuthGuard implements CanActivate {
    constructor(private authService: AuthService, private router: Router, private http: Http) { }

    canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
        if(this.authService.authenticate()){
            return true;
        }else{
            this.router.navigate(['/register])
            return false;
        }
    }
}

What am I missing?

auth.guard.ts (version 3)

export class AuthGuard implements CanActivate {
    constructor(private authService: AuthService, private router: Router, private http: Http) { }

    canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
        return this.authService.authenticate().map((res) => {
            if (res.response) {
                return true;
            } else {
                this.router.navigate(['/register']);
                return false;
            }
        })

    }
}

Above code will chain your observables. But there's another problem with your code -- if(res.response) {return true} , when there's response, it could be 'user exists and logged in' or 'user does not exists'. So you are returning true for both cases. That you need fix.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM