Асинхронная защита в угловых 6 - angular


1

Я хотел бы предоставить аутентификацию на стороне сервера, прежде чем я получу доступ к определенному маршруту в угловом формате.

У меня есть AuthGuard, который реализует CanActivate и службу AuthService. У authService уже есть private loggedIn: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(null); который просматривает подписку, чтобы узнать, зарегистрирован ли пользователь или нет. Я действительно не знаю, ошибочен ли мой подход, но он, похоже, не работает.

Это то, что у меня есть в auth.guard.ts:

canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot) : Observable<boolean> {
    return this.authService.isAuthenticated().map((isLoggedIn) => {
        if (isLoggedIn) {
            return true;
        } else {
            this.router.navigate([/login]);
            return false;
        }
    })
}

и это auth.service.ts:

    @Injectable()
export class AuthService {
    private loggedIn: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(null);

    constructor(
        private router: Router,
        private http: HttpClient
    ) {

    }

    get isLoggedIn() {
        return this.loggedIn.asObservable();
    }

    isAuthenticated() : Observable<boolean> {
        const headers = new HttpHeaders().set("X-Requested-With", "XMLHttpRequest");

        return this.http.get(/user, {headers: headers}).map(
            response => {
                if (response[username]) {
                    this.loggedIn.next(true);
                    return true;
                } else {
                    return false;
                }
            }
        )
    }
Источник
  •  54
  •  2
  • 9 мар 2020 2020-03-09 19:38:54

2 ответа

0

Вот подход к RXJS6, добавлена переменная _isAuthenticated в службе аутентификации, чтобы запросить состояние сервера только тогда, когда флаг отключен. Надеюсь, это поможет другим.

Убедитесь, что canActivate возвращает простое логическое или наблюдаемое. Обработчик маршрута будет подписаться на данный наблюдаемый и реагирует на первое логическое значение, исходящее из потока значений.

auth.guard.ts

import { Injectable } from @angular/core;
import { Router, CanActivate } from @angular/router;

import { Observable } from rxjs/;
import { map, finalize } from rxjs/operators;
import { DataService } from ../data.service;
import { AuthenticationService } from ./authentication.service;

@Injectable()
export class AuthenticationGuard implements CanActivate {

  constructor(private router: Router,
              private dataService: DataService,
              private authenticationService: AuthenticationService) { }

  canActivate(): any {
    const isAuthenticated = this.authenticationService.isAuthenticated();

    // All good
    if ( isAuthenticated ) {
      return true;

    // Hmm, let verify the user first
    } else {
      return this.authenticationService.isSessionAlive()
        .pipe(
          map(res => {

            // No valid session; let move to the login page
            if ( res === false ) {
              this.router.navigate([/login], { replaceUrl: true });
            }

            return res;
          })
        );
    }
  }

}

auth.service.ts (я использую rxjs 6)

import { Injectable } from @angular/core;
import { Observable } from rxjs;
import { DataService } from @app/core;

@Injectable()
export class AuthenticationService {

  private _isAuthenticated = false;

  constructor(
    private dataService: DataService
  ) {}

  isAuthenticated(): boolean {
    return this._isAuthenticated;
  }

  isSessionAlive(): Observable<any> {
    return Observable.create((observer) => {
      this.dataService.SessionIsAlive()
        .subscribe((res) => {
          this._isAuthenticated = true;
          observer.next(res.success); // your server response
        }, (err) => {
          this._isAuthenticated = false;
          observer.next(false);
          // observer.error(err); // wont work here you need to use next
        });
    });
  }
}
  • 9 мар 2020 2020-03-09 19:38:54
0

Вы можете сделать бит изменений следующим образом:

Ваше обслуживание,

@Injectable()
export class LoginService {
  public isUserLoggedIn: boolean;
  constructor(
    private router: Router,
    private auth: AuthService) {
    this.isUserLoggedIn = false;
  }

  public loginService(data): void {
    this.auth.isAuthentication(data)
    .subscribe((response) => {
      if (response) {
        this.isUserLoggedIn = true;             
      }else {
        this.router.navigate([login]);
      }
    });
  }

 public getUserLoggedIn() {
   return this.isUserLoggedIn;
}

а потом,

@Injectable()
export class AuthGuard implements CanActivate {
  constructor(private login: LoginService) { }
  canActivate(
    next: ActivatedRouteSnapshot,
    state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean {
    return this.login.getUserLoggedIn();
  }
}