我正在尝试使用最新版本的Firebase和Angular。我试图实现的总体概念是管理员身份验证。我已经实现了登录注销功能,并将googleAuth登录用户保存到具有UID的数据库中。 而且我试图将某些页面限制为“登录”和“管理”。我已将isAdmin:true分配为数据库中存储的用户对象中的值。我想查看用户是否为admin并为路由器参数返回true或false。
这是我所拥有的:
import { Injectable } from '@angular/core';
import { AngularFireDatabase, FirebaseObjectObservable } from 'angularfire2/database';
import * as firebase from 'firebase';
import { AppUser } from './models/app-user';
@Injectable({
providedIn: 'root'
})
user.service.ts
export class UserService {
constructor(private db: AngularFireDatabase) { }
save(user: firebase.User){
this.db.object('/users/' + user.uid).update({
name: user.displayName,
email: user.email
});
}
get(uid:string): FirebaseObjectObservable<AppUser>{
return this.db.object('/users/' +uid);
}
}
app.module.ts 从“ @ angular / platform-browser”导入{BrowserModule}; 从'@ angular / core'导入{NgModule}; 从“ angularfire2”导入{AngularFireModule}; 从“ angularfire2 /数据库”导入{AngularFireDatabaseModule}; 从“ angularfire2 / auth”导入{AngularFireAuthModule}; 从“ @ angular / router”导入{RouterModule}; 从“ @ ng-bootstrap / ng-bootstrap”导入{NgbModule}; 从“ ./bs-navbar/bs-navbar.component”导入{BsNavbarComponent}; 从'./home/home.component'导入{HomeComponent}; 从“ ./products/products.component”导入{ProductsComponent}; 从“ ./shopping-cart/shopping-cart.component”导入{ShoppingCartComponent}; 从“ ./check-out/check-out.component”导入{CheckOutComponent}; 从'./order-success/order-success.component'导入{OrderSuccessComponent}; 从“ ./my-orders/my-orders.component”导入{MyOrdersComponent}; 从“ ./admin/admin-products/admin-products.component”导入{AdminProductsComponent}; 从“ ./admin/admin-orders/admin-orders.component”导入{AdminOrdersComponent}; 从“ ./login/login.component”导入{LoginComponent}; 从'./app.component'导入{AppComponent}; 从'src / environments / environment'导入{环境}; 从“ ./auth.service”导入{AuthService}; 从“ ./auth-guard.service”导入{AuthGuard as AuthGuard); 从“ ./user.service”导入{UserService}; 从“ ./admin-auth-guard.service”导入{AdminAuthGuard as AdminAuthGuard};
@NgModule({
declarations: [
AppComponent,
BsNavbarComponent,
HomeComponent,
ProductsComponent,
ShoppingCartComponent,
CheckOutComponent,
OrderSuccessComponent,
MyOrdersComponent,
AdminProductsComponent,
AdminOrdersComponent,
LoginComponent,
ShoppingCartComponent
],
imports: [
BrowserModule,
AngularFireModule.initializeApp(environment.firebase),
AngularFireDatabaseModule,
AngularFireAuthModule,
NgbModule.forRoot(),
RouterModule.forRoot([
{path: '', component: HomeComponent},
{path: 'products', component: ProductsComponent},
{path: 'shopping-cart', component: ShoppingCartComponent},
{path: 'login', component: LoginComponent},
{path: 'check-out', component: CheckOutComponent,canActivate:[AuthGuard]},
{path: 'order-success', component: OrderSuccessComponent, canActivate:[AuthGuard]},
{path: 'my/orders',component: MyOrdersComponent,canActivate:[AuthGuard]},
{path: 'admin/products', component: AdminProductsComponent,canActivate:[AuthGuard,AdminAuthGuard]},
{path: 'admin/orders', component: AdminOrdersComponent,canActivate:[AuthGuard,AdminAuthGuard]}
])
],
providers: [
AuthService,
AuthGuard,
AdminAuthGuard,
UserService
],
bootstrap: [AppComponent]
})
export class AppModule { }
admin-auth-guard.service.ts
import { Injectable } from '@angular/core';
import { CanActivate } from '@angular/router';
import { AuthService } from './auth.service';
import { UserService } from './user.service';
import { Observable } from 'rxjs/Observable';
import { switchMap, map } from 'rxjs/operators';
@Injectable({
providedIn: 'root'
})
export class AdminAuthGuard implements CanActivate {
constructor(private auth: AuthService, private userService: UserService) { }
canActivate(): Observable<boolean>{
return this.auth.user$.pipe(
switchMap(user => this.userService.get(user.uid)),
map(appUser => appUser.isAdmin)
);
}
}
答案 0 :(得分:0)
这样做可以向普通用户显示是否允许他访问该页面。但这必须通过安全规则来完成。如果不是这样的话,将允许任何用户劫持Javascript页面并使自己成为管理员,并可以访问非普通用户使用的秘密页面。
一种更干净的方法是拥有一个包含所有允许用户的用户ID的对象的最高列表。并对照清单进行检查。该列表必须是只读的,或者只能由管理员访问。这是通过安全规则完成的。
答案 1 :(得分:0)
您使用了displayname属性吗?在进行用户或管理员注册时,您可以添加此属性,并将其保存在authentication db中。因此,在登录功能中,您可以检查displayname属性是admin还是user。这很简单。