Angular 2 AuthGuard + Firebase 身份验证
Angular 2 AuthGuard + Firebase Auth
我正在尝试使用 Firebase Auth 为 Angular 2 条路由构建 AuthGuard。
这是 AuthGuard 服务:
import { Injectable } from '@angular/core';
import { CanActivate, Router,
ActivatedRouteSnapshot,
RouterStateSnapshot } from '@angular/router';
import { AuthService } from './auth.service';
@Injectable()
export class AuthGuard implements CanActivate {
constructor(private AuthService: AuthService,
private router: Router) {}
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
if (this.AuthService.loggedIn) { return true; }
this.router.navigate(['login']);
return false;
}
}
这是 AuthService,它检查用户是否登录并将结果绑定到其构造函数中的 属性 'loggedIn'。
import { Injectable } from '@angular/core';
import { AngularFire } from 'angularfire2';
import { Router } from '@angular/router';
@Injectable()
export class AuthService {
loggedIn: boolean = false;
constructor(
public af: AngularFire,
public router: Router) {
af.auth.subscribe(user => {
if(user){
this.loggedIn = true;
}
});
}
}
这里的问题很明显是异步的。 AuthGuard 的 canActivate() 始终 return 是一个假值,因为订阅没有及时收到数据以将 'loggedIn' 更改为真。
解决此问题的最佳做法是什么?
编辑:
将 AuthGuard 更改为 return 可观察的。
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
return this.af.auth.map((auth) => {
if (!auth) {
this.router.navigateByUrl('login');
return false;
}
return true;
});
}
它有点工作,因为你没有被重定向到登录...但是目标 AuthGuarded 组件没有呈现。
不确定这是否与我的app.routes有关。这是该部分的代码:
const routes: Routes = [
{ path: '', component: MainComponent, canActivate: [AuthGuard] },
...
];
export const routing = RouterModule.forRoot(routes);
使用 .take(1) 完成可观察对象以使组件呈现。
import {Observable} from "rxjs/Observable";
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/take';
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
return this.af.auth.map((auth) => {
if (!auth) {
this.router.navigateByUrl('login');
return false;
}
return true;
}).take(1);
}
对于较新版本的 AngularFire
,您必须改用 authState
:
@Injectable()
export class AuthGuard implements CanActivate {
constructor(
private afAuth: AngularFireAuth,
private router: Router
) {}
canActivate(): Observable<boolean> {
return this.afAuth.authState
.take(1)
.map(authState => !!authState)
.do(auth => !auth ? this.router.navigate(['/login']) : true);
}
}
不要忘记从 rxjs/add/operator
.
导入 take
、map
和 do
已经用 Angular 11 和 angular 火 6 测试了这个
canActivate(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
return this.authService.afAuth.authState.pipe(
map(authState => !!authState),
map(auth => {
if (!auth) {
this.router.navigate(['/sign-in']);
}
return auth;
}),
);
}
我正在尝试使用 Firebase Auth 为 Angular 2 条路由构建 AuthGuard。
这是 AuthGuard 服务:
import { Injectable } from '@angular/core';
import { CanActivate, Router,
ActivatedRouteSnapshot,
RouterStateSnapshot } from '@angular/router';
import { AuthService } from './auth.service';
@Injectable()
export class AuthGuard implements CanActivate {
constructor(private AuthService: AuthService,
private router: Router) {}
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
if (this.AuthService.loggedIn) { return true; }
this.router.navigate(['login']);
return false;
}
}
这是 AuthService,它检查用户是否登录并将结果绑定到其构造函数中的 属性 'loggedIn'。
import { Injectable } from '@angular/core';
import { AngularFire } from 'angularfire2';
import { Router } from '@angular/router';
@Injectable()
export class AuthService {
loggedIn: boolean = false;
constructor(
public af: AngularFire,
public router: Router) {
af.auth.subscribe(user => {
if(user){
this.loggedIn = true;
}
});
}
}
这里的问题很明显是异步的。 AuthGuard 的 canActivate() 始终 return 是一个假值,因为订阅没有及时收到数据以将 'loggedIn' 更改为真。
解决此问题的最佳做法是什么?
编辑:
将 AuthGuard 更改为 return 可观察的。
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
return this.af.auth.map((auth) => {
if (!auth) {
this.router.navigateByUrl('login');
return false;
}
return true;
});
}
它有点工作,因为你没有被重定向到登录...但是目标 AuthGuarded 组件没有呈现。
不确定这是否与我的app.routes有关。这是该部分的代码:
const routes: Routes = [
{ path: '', component: MainComponent, canActivate: [AuthGuard] },
...
];
export const routing = RouterModule.forRoot(routes);
使用 .take(1) 完成可观察对象以使组件呈现。
import {Observable} from "rxjs/Observable";
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/take';
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
return this.af.auth.map((auth) => {
if (!auth) {
this.router.navigateByUrl('login');
return false;
}
return true;
}).take(1);
}
对于较新版本的 AngularFire
,您必须改用 authState
:
@Injectable()
export class AuthGuard implements CanActivate {
constructor(
private afAuth: AngularFireAuth,
private router: Router
) {}
canActivate(): Observable<boolean> {
return this.afAuth.authState
.take(1)
.map(authState => !!authState)
.do(auth => !auth ? this.router.navigate(['/login']) : true);
}
}
不要忘记从 rxjs/add/operator
.
take
、map
和 do
已经用 Angular 11 和 angular 火 6 测试了这个
canActivate(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
return this.authService.afAuth.authState.pipe(
map(authState => !!authState),
map(auth => {
if (!auth) {
this.router.navigate(['/sign-in']);
}
return auth;
}),
);
}