Eva*_*ter 59 typescript angular2-routing angular
我正在尝试使用Angular2路由器防护来限制对我的应用程序中某些页面的访问.我正在使用Firebase身份验证.为了检查用户是否使用Firebase登录,我必须使用回调调用.subscribe()该FirebaseAuth对象.这是守卫的代码:
import { CanActivate, Router, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
import { AngularFireAuth } from "angularfire2/angularfire2";
import { Injectable } from "@angular/core";
import { Observable } from "rxjs/Rx";
@Injectable()
export class AuthGuard implements CanActivate {
constructor(private auth: AngularFireAuth, private router: Router) {}
canActivate(route:ActivatedRouteSnapshot, state:RouterStateSnapshot):Observable<boolean>|boolean {
this.auth.subscribe((auth) => {
if (auth) {
console.log('authenticated');
return true;
}
console.log('not authenticated');
this.router.navigateByUrl('/login');
return false;
});
}
}
Run Code Online (Sandbox Code Playgroud)
当导航到对其具有防护的页面时authenticated,或者not authenticated打印到控制台(在等待来自firebase的响应的一些延迟之后).但是,导航永远不会完成.此外,如果我没有登录,我将被重定向到该/login路线.因此,我遇到的问题是return true不向用户显示请求的页面.我假设这是因为我正在使用回调,但我无法弄清楚如何做到这一点.有什么想法吗?
Gün*_*uer 94
canActivate需要返回Observable完成的内容:
@Injectable()
export class AuthGuard implements CanActivate {
constructor(private auth: AngularFireAuth, private router: Router) {}
canActivate(route:ActivatedRouteSnapshot, state:RouterStateSnapshot):Observable<boolean>|boolean {
return this.auth.map((auth) => {
if (auth) {
console.log('authenticated');
return true;
}
console.log('not authenticated');
this.router.navigateByUrl('/login');
return false;
}).first(); // this might not be necessary - ensure `first` is imported if you use it
}
}
Run Code Online (Sandbox Code Playgroud)
有一个return缺失,我使用map()而不是subscribe()因为subscribe()返回一个Subscription不是Observable
小智 16
您可能会Observable用来处理异步逻辑部分.以下是我测试的代码示例:
import { Injectable } from '@angular/core';
import { CanActivate } from '@angular/router';
import { Observable } from 'rxjs/Observable';
import { DetailService } from './detail.service';
@Injectable()
export class DetailGuard implements CanActivate {
constructor(
private detailService: DetailService
) {}
public canActivate(): boolean|Observable<boolean> {
if (this.detailService.tempData) {
return true;
} else {
console.log('loading...');
return new Observable<boolean>((observer) => {
setTimeout(() => {
console.log('done!');
this.detailService.tempData = [1, 2, 3];
observer.next(true);
observer.complete();
}, 1000 * 5);
});
}
}
}
Run Code Online (Sandbox Code Playgroud)
在最新版本的 AngularFire 中,以下代码有效(与最佳答案相关)。注意“管道”方法的用法。
import { Injectable } from '@angular/core';
import {ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot} from '@angular/router';
import {AngularFireAuth} from '@angular/fire/auth';
import {map} from 'rxjs/operators';
import {Observable} from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class AuthGuardService implements CanActivate {
constructor(private afAuth: AngularFireAuth, private router: Router) {
}
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean {
return this.afAuth.authState.pipe(
map(user => {
if(user) {
return true;
} else {
this.router.navigate(['/login']);
return false;
}
})
);
}
}Run Code Online (Sandbox Code Playgroud)
扩展最流行的答案。AngularFire2的Auth API有所更改。这是实现AngularFire2 AuthGuard的新签名:
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { AngularFireAuth } from 'angularfire2/auth';
import { CanActivate, Router, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
@Injectable()
export class AuthGuardService implements CanActivate {
constructor(
private auth: AngularFireAuth,
private router : Router
) {}
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot):Observable<boolean>|boolean {
return this.auth.authState.map(User => {
return (User) ? true : false;
});
}
}
Run Code Online (Sandbox Code Playgroud)
注意:这是一个相当幼稚的测试。您可以控制台记录用户实例,以查看是否要针对用户的一些更详细的方面进行测试。但至少应帮助保护针对未登录用户的路由。
您可以返回true | false作为承诺。
import {Injectable} from '@angular/core';
import {ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot} from '@angular/router';
import {Observable} from 'rxjs';
import {AuthService} from "../services/authorization.service";
@Injectable()
export class AuthGuard implements CanActivate {
constructor(private router: Router, private authService:AuthService) { }
canActivate(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean {
return new Promise((resolve, reject) => {
this.authService.getAccessRights().then((response) => {
let result = <any>response;
let url = state.url.substr(1,state.url.length);
if(url == 'getDepartment'){
if(result.getDepartment){
resolve(true);
} else {
this.router.navigate(['login']);
resolve(false);
}
}
})
})
}
}
Run Code Online (Sandbox Code Playgroud)
为了展示另一种实现方式。根据文档,以及其他答案提到的 CanActivate 返回类型也可以是解析为布尔值的 Promise。
注意:所示示例是在 Angular 11 中实现的,但适用于 Angular 2+ 版本。
例子:
import {
Injectable
} from '@angular/core';
import {
ActivatedRouteSnapshot,
CanActivate,
CanActivateChild,
Router,
RouterStateSnapshot,
UrlTree
} from '@angular/router';
import {
Observable
} from 'rxjs/Observable';
import {
AuthService
} from './auth.service';
@Injectable()
export class AuthGuardService implements CanActivate, CanActivateChild {
constructor(private authService: AuthService, private router: Router) {}
canActivate(
route: ActivatedRouteSnapshot, state: RouterStateSnapshot
): Observable < boolean | UrlTree > | Promise < boolean | UrlTree > | boolean | UrlTree {
return this.checkAuthentication();
}
async checkAuthentication(): Promise < boolean > {
// Implement your authentication in authService
const isAuthenticate: boolean = await this.authService.isAuthenticated();
return isAuthenticate;
}
canActivateChild(
childRoute: ActivatedRouteSnapshot, state: RouterStateSnapshot
): Observable < boolean | UrlTree > | Promise < boolean | UrlTree > | boolean | UrlTree {
return this.canActivate(childRoute, state);
}
}Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
38443 次 |
| 最近记录: |