具有http请求和可观察量的Angular2 auth防护

Tim*_*Tim 5 authentication observable angular2-routing angular2-http angular

我目前正在实现一个带有spring boot作为后端的angular2示例应用程序.我在前端auth保护机制和observables方面遇到了一些问题.

我想要实现:

  1. 当有人进入受保护的路线时,验证员应检查用户是否已设置在auth服务变量中
  2. 如果未设置,则应发出http请求以检查会话是否可用
  3. service方法应返回true/false值(由于可能的http请求而异步)
  4. 如果服务返回false,则auth guard应重定向到登录页面
  5. auth guard应返回true/false,以便激活或不激活路由

我的代码目前看起来像这样(我正在使用RC5顺便说一句.):

Auth Guard

import {Injectable} from "@angular/core";
import {CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, Router} from "@angular/router";
import {Observable, Subject} from "rxjs/Rx";
import {AuthService} from "./auth.service";

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

  canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> | boolean {
    var authenticated = this.authService.isAuthenticated();
    var subject = new Subject<boolean>();
    authenticated.subscribe(
        (res) => {
          console.log("onNext guard: "+res);
          if(!res && state.url !== '/signin') {
            console.log("redirecting to signin")
            this.router.navigate(['/signin']);
          }
          subject.next(res);
        });
    return subject.asObservable();
  }
}
Run Code Online (Sandbox Code Playgroud)

验证服务

import {Injectable} from "@angular/core";
import {User} from "./user.interface";
import {Router} from "@angular/router";
import {Http, Response, Headers} from "@angular/http";
import {environment} from "../environments/environment";
import {Observable, Observer, Subject} from "rxjs/Rx";

@Injectable()
export class AuthService {
  private authenticatedUser : User;
  constructor(private router: Router, private http: Http) {}

  signupUser(user: User) {
  }


  logout() {
    //do logout stuff
    this.router.navigate(['/signin']);
  }

  isAuthenticated() : Observable<boolean> {
    var subject = new Subject<boolean>();
    if (this.authenticatedUser) {
      subject.next(true);
    } else {
      this.http.get(environment.baseUrl + '/user')
        .map((res : Response) => res.json())
        .subscribe(res => {
          console.log("next: returning true");
          this.authenticatedUser = User.ofJson(res);
          subject.next(true);
        }, (res) => {
          console.log("next: returning false");
          subject.next(false);
        });
    }
    return subject.asObservable();
  }
}
Run Code Online (Sandbox Code Playgroud)

问题是:即使我登录时,警卫也从不允许路由器组件激活.

谢谢您的帮助!

Gün*_*uer 9

更改

return subject.asObservable();
Run Code Online (Sandbox Code Playgroud)

return subject.asObservable().first();
Run Code Online (Sandbox Code Playgroud)

路由器等待observable完成.first()在第一次活动结束后完成.

  • 我不得不使用BehavorSubject(Service)和ReplaySubject(guard)的组合,但它现在按预期工作.谢谢! (3认同)
  • @Tim你能分享一些工作解决方案的代码示例吗?我遇到了同样的问题,看到一个有用的例子会非常有帮助.谢谢. (2认同)