问题描述
我正在firestore auth中动态创建用户,并添加了多种类型的声明,例如admin,讲师,助手.到目前为止,我已经能够使用新创建的用户登录并根据我提供的登录凭据将声明属性设置为true,即admin: true
,instructor: true
.但是我无法在路由中正确设置[AuthGuard]
,甚至没有登录也无法使用url重定向到组件,这应该不会发生.我对如何正确添加AuthGuard
感到有些困惑.这是我的代码
I am creating users dynamically in firestore auth and have added multiple types of claims i.e admin, instructor, assistant. So far i am able to login using the new created users and getting claims property as true i.e admin: true
, instructor: true
according to the login credentials i am providing. But i am unable to set up [AuthGuard]
properly in routes and without even logging in i am able to redirect to components using urls and this should not be happening. I am a little bit confused as to how can i properly add AuthGuard
. Here is my code
auth-service.ts
auth-service.ts
import * as firebase from 'firebase/app';
import { AngularFireAuth } from '@angular/fire/auth';
import { AngularFirestore } from '@angular/fire/firestore';
import { Injectable } from '@angular/core';
import { JwtHelperService } from '@auth0/angular-jwt';
import { Observable } from 'rxjs/Observable';
import { Router } from "@angular/router";
@Injectable()
export class AuthService {
public user: Observable<firebase.User>;
public userDetails: firebase.User = null;
constructor(private _firebaseAuth: AngularFireAuth, private router: Router,
private _firestore: AngularFirestore,
public jwtHelper: JwtHelperService ) {
this.user = _firebaseAuth.authState;
this.user.subscribe(
(user) => {
if(user) {
this.userDetails = user;
this._firebaseAuth.auth.currentUser.getIdTokenResult(true).then(res => {
user= res.claims;
})
}
else {
this.userDetails = null;
}
}
);
}
}
auth-guard.service.ts
auth-guard.service.ts
import 'rxjs/add/operator/do';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/take';
import { CanActivate, Router } from '@angular/router';
import { AuthService } from './auth-service.service';
import { Injectable } from "@angular/core";
import { Observable } from "rxjs/Rx";
import { tap } from 'rxjs/operators';
@Injectable()
export class AuthGuard implements CanActivate {
constructor(private auth: AuthService, private router: Router) { }
canActivate() {
return this.auth.user
.take(1)
.map(authState => !!authState)
.do(authenticated => {
if (!authenticated) {
this.router.navigate(['auth/login']);
}
});
}
}
app-routing.module.ts
app-routing.module.ts
import { ExtraOptions, RouterModule, Routes } from '@angular/router';
import { AuthGuard } from './auth/auth-guard.service';
import { LoginComponent } from './auth/login/login.component'
import {
NbAuthComponent,
} from '@nebular/auth';
import { NgModule } from '@angular/core';
import { RegisterComponent } from './auth/register/register.component';
import { RequestPasswordComponent } from './auth/request-password/request-password.component';
import { ResetPasswordComponent } from './auth/reset-password/reset-password.component';
const routes: Routes = [
{
path: 'pages',
canActivate: [AuthGuard],
loadChildren: () => import('../app/pages/pages.module')
.then(m => m.PagesModule),
},
{
path: 'studentcourseregistration',
loadChildren: () => import('../app/studentcourseregistration/studentcourseregistration.module')
.then(m => m.StudentcourseregistrationModule),
},
{
path: 'auth',
component: NbAuthComponent,
children: [
{
path: '',
component: LoginComponent,
},
{
path: 'login',
component: LoginComponent,
},
{
path: 'register',
component: RegisterComponent,
},
// {
// path: 'logout',
// component: ,
// },
{
path: 'request-password',
component: RequestPasswordComponent,
},
{
path: 'reset-password',
component: ResetPasswordComponent,
},
],
},
// {
// path: 'student',
// loadChildren: () => import('../student/student.module')
// .then(m => m.StudentModule),
// },
{ path: '', redirectTo: 'auth/login', pathMatch: 'full' },
{ path: '**', redirectTo: 'pages' },
];
const config: ExtraOptions = {
useHash: false,
};
@NgModule({
imports: [RouterModule.forRoot(routes, config)],
exports: [RouterModule],
})
export class AppRoutingModule {
}
像这样在auth中添加新用户
adding new user in auth like this
this._firebaseAuth.auth.createUserWithEmailAndPassword(this.user.email, this.user.password)
.then(cred => {
const adminRole = firebase.functions().httpsCallable('addAdminRole');
adminRole({email: this.user.email}).then(res => {
console.log(res);
})
})
推荐答案
会是这样的:
import { CanActivate, Router } from '@angular/router';
import { Injectable } from "@angular/core";
import { AngularFireAuth } from '@angular/fire/auth';
import { take, switchMap } from 'rxjs/operators';
@Injectable()
export class AdminGuard implements CanActivate {
constructor(private auth: AngularFireAuth, private router: Router) { }
canActivate() {
return this.auth.authState.pipe(
take(1),
switchMap(async (authState) => {
if (authState) { // check are user is logged in
const token = await authState.getIdTokenResult()
if (!token.claims.admin) { // check claims
this.router.navigate(['/auth/login'])
return false
} else {
return true
}
} else {
this.router.navigate(['/auth/login'])
return false
}
}),
)
}
}
这篇关于使用自定义声明的Angular和Firebase路由守卫的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!