使用Angle 6和Firebase保护管理员路由

时间:2018-09-29 14:18:52

标签: angular firebase firebase-realtime-database angular6

我正在使用Firebase使用Angular6。我目前是Angular的新手。我正在从codewithmosh学习Mosh Hamedani的课程。但是问题是我正在使用angular6和我在Angular4中观看的教程。

现在我正在使用保护管理员路由。在Firebase中定义一些凭证的地方。

如果用户是管理员,则必须使用显示和隐藏功能。

这是有关Firebase中用户的数据定义。

enter image description here

admin-auth-guard.service.ts

在使用此amdin-auth文件时出现错误。

enter image description here

auth.service.ts

enter image description here

user.service.ts

enter image description here

app-user.ts

enter image description here

5 个答案:

答案 0 :(得分:1)

如果显示错误而不是像突出显示那样会更好。无论如何,对于路线守卫来说,这就是我实现的目标。

auth.service.ts

export class AuthService {
  user$: Observable<AppUser>;
  constructor(private afAuth: AngularFireAuth, private db: AngularFireDatabase) 
 {
     this.user$ = this.afAuth.authState
      .pipe(switchMap(user_ => {
        if (user_) {
          return this.db.object(`users/${user_.uid}`).valueChanges();
        } else {
          return of(null);
        }
      }));
 }
}

这样,每当您订阅可观察的用户$时,您始终会从实时数据库中获得用户的对象。

然后,在 admin-auth-guard.service.ts 中:

constructor(private _auth: AuthService,
              private _router: Router) {
  }

canActivate(
    next: ActivatedRouteSnapshot,
    state: RouterStateSnapshot): Observable<boolean> | 
    Promise<boolean> | boolean {

    return this._auth.user$.pipe(
      take(1),
      map(user => user && user.admin),
      tap(isAdmin => {
        if (!isAdmin) {
          console.error('Access denied - Admins only');
// re-route to wherever you want 
          this.router.navigate(['login']); 
        }
      })
    );

  } 

希望这会有所帮助。

答案 1 :(得分:1)

您对user.service.ts中仍在使用角度实时数据库进行的更改是可以的,您只需要更改canActivate方法即可。 userService.get(user.uid)返回angularfireobject,您需要通过调用.valueChanges()将其转换为可观察的对象。就是这样。

canActivate() : Observable<boolean>{
      return this.auth.user$
        .switchMap( user => { 
                return this.userService.get(user.uid).valueChanges();
              } )
              .map( appUser => appUser.isAdmin);

    }

答案 2 :(得分:0)

我认为这只是Typescript编译时检查,如果您运行该应用程序并对其进行测试以查看控制台上的错误会更好,但是要解决此问题,您需要使用AppUser接口注释appUser,如下所示:

 canActivate() {
    return this.afService.user$.pipe(
      switchMap(result => this.userService.get(result.uid)),
      map((userApp: AppUser) => userApp.isAdmin)
    );
  }

我还使用了回车键和花括号,因为它们只是一个箭头功能,因为它们没用,所以这段代码是相等的

switchMap(result => this.userService.get(result.uid))

此代码

switchMap(result => {
   return this.userService.get(result.uid)
})

但是我不太确定为什么switchMap中的(用户)突出显示,如果您发布错误消息,如果先前的答案没有帮助,我可能会提供帮助。

答案 3 :(得分:0)

我已经修改了您的方法,看看它是否有效

首先在logout()方法之后在auth.service.ts中添加以下方法

get appUser$() : Observable<AppUser> {
      return this.user$.pipe(switchMap(user => {
        if (user) return this.userService.get(user.uid).valueChanges();

        return of(null); 
      }))
}

,然后在canActivate()方法中进行更改

canActivate(): Observable<boolean> {
    return this.afService.appUser$
    .pipe(map (appUser => appUser.isAdmin));
}

只需注意我在Angular 7中构建的Github My Github Link上的项目即可。您的Angular 6项目将正常工作。

答案 4 :(得分:0)

Activate必须返回什么? Observable,对吧?

但是,您返回的AngularFireObject并不是可观察的。

因此,在您的 user.service.ts 文件中,使用valueChanges()方法将返回Observable

get(uid: string): Observable<AppUser> {
  return this.db.object<AppUser>('/users/' + uid).valueChanges();
}

并在您的 admin-auth-guard.service.ts 文件中,

canActivate(): Observable<boolean> {
  return this.afService.user$.pipe(
    switchMap(({uid}) => this.userService.get(uid)),
    map(user => user.isAdmin)
  );
}

要更好地理解: https://forum.codewithmosh.com/d/1210-oshop-protecting-admin-routes-not-able-to-get-uid-from-firebase/20