【问题标题】:Writing a route guard to wait for auth in AngularFire and Angularjs 2在 AngularFire 和 Angularjs 2 中编写路由守卫以等待身份验证
【发布时间】:2016-07-24 16:05:05
【问题描述】:

我正在尝试在 Angular.js 2 (2.0.0-rc.4)(由 angular cli 创建)中编写一个路由器保护,等待 AngularFire (2.0.0-beta.2) 检查登录状态并记录如果用户在允许进入状态之前已经登录,则用户(匿名)进入。

我的守护密码是:

canActivate() {
    /* This part is to detect auth changes and log user in anonymously */
    this.auth
      .subscribe(auth => {
        if (!auth) {
          this.auth.login();
        }
      });

    /* This part is to listen to auth changes and IF there is an auth, resolves this guard with a true to let user in */ 
    return this.auth
      .asObservable()
      .filter(auth => {
        return auth ? true : false;
      })
      .map(x => {
        console.log("TEST 1000");
        return true;
      });
 }

当我运行应用程序时,即使我看到 TEST 1000 控制台输出表明 canActivate() 返回了 true 我的路由没有激活。

我想知道我的逻辑是否有错误的想法,或者有什么聪明的想法可以智能地调试它。

【问题讨论】:

    标签: angular firebase rxjs firebase-authentication angularfire2


    【解决方案1】:

    我目前正在使用它来检查身份验证以及用户是否是管理员:

    认证服务:

    import { Injectable } from '@angular/core';
    
    import { Router } from '@angular/router';
    
    import { AngularFire } from 'angularfire2';
    
    
    import { Observable } from 'rxjs/Observable';
    
    import { Subject } from 'rxjs/Rx';
    
    
    @Injectable()
    
    export class AuthService {
    
    
      admin$: Subject<boolean>;
    
    
      private user: any = null;
    
    
      constructor(private af: AngularFire, private router: Router) {
    
        this.admin$ = <Subject<boolean>>new Subject();
    
        this.af.auth.subscribe(
    
          auth => {
    
            if(auth){
    
              this.user = af.database.object(`users_list/${auth.uid}`).subscribe(
    
                res => {
    
                  this.user = res;
    
                  this.admin$.next(this.user.role === 10);
    
                  this.admin$.complete();
    
                },
    
                err => this.admin$.error(err)
    
              );
    
            }else{
    
              this.router.navigate(['auth']);
    
              this.admin$.next(false);
    
              this.admin$.complete();
    
            }
    
          }
    
        );
    
      }
    
    
      doLogin(credentials){
    
        this.admin$ = <Subject<boolean>>new Subject();
    
        this.af.auth.login(credentials);
    
      }
    
    
      admin() {
    
        return this.admin$;
    
      }
    
    }
    

    身份验证服务:

    constructor(private authService: AuthService, private router: Router) { }
    
    
      canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> | boolean {
    
    
        this.authService.admin().subscribe(
    
          res => {
    
            // Navigate to the login page
    
            if(!res) {
    
              this.router.navigate(['/auth']);
    
            }
    
          },
    
          err => console.log(err),
    
          () => {
    
            // console.log('auth guard can activate complete')
    
          }
    
        );
    
    
        return this.authService.admin();
    
      }
    

    现在,这与您的问题的关系是,如果不在 admin$ 上调用 complete(),它将无法正常工作。控制台会记录true,但路由器不会导航到下一个状态。

    我几乎还在掌握 observables 的窍门(因此实现很差),如果你要修复你的代码,我真的很想看到最终结果,因为它看起来更干净,而且可能更好方法来做到这一点。干杯!

    【讨论】:

    • 你是对的!我的问题是,确实,它并不完整。我用take(1) 更改了`.asObservable()`,只期望一个值,然后完成它,它开始工作了!
    【解决方案2】:

    你能测试一下这是否能解决你的问题

    canActivate() {
    
        this.auth
          .subscribe(auth => {
              if (!auth) this.auth.login()
           });
        let authObs = this.auth
          .asObservable()
          .filter(auth => auth ? true : false)
          .map(x => {
              console.log("TEST 1000");
              return true;
           });
    
        authObs.subscribe(a => return true);
    

    我认为问题在于您只创建了 observable 而实际上并没有订阅它。 CanActivate 期望一个 promise 或 bool 而不是 observable。

    【讨论】:

    • 嗨 Filip,我试过了,但不幸的是 canActivate() 期望的类型是 Observable&lt;boolean&gt;boolean,所以你的没有编译。 export interface CanActivate { canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable&lt;boolean&gt; | boolean; }是它的接口,按照cli的默认设置,希望是最新的。
    • 我指的是 angular.io 上的文档。导出 CanActivate(options : CanActivateAnnotation) : (hook: (next: ComponentInstruction, prev: ComponentInstruction) => Promise| boolean)。你可能是我真的不知道的最新消息。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-01-10
    • 2015-11-30
    • 2019-11-30
    • 1970-01-01
    • 2015-04-28
    • 1970-01-01
    • 2021-05-01
    相关资源
    最近更新 更多