Angular2가 비동기 함수 호출을 활성화()할 수 있습니다.
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;
});
}
}
가드가 있는 페이지로 이동할 때 다음 중 하나를 선택합니다.authenticated또는not authenticated콘솔에 인쇄됩니다(화재 기지의 응답을 기다리는 동안 잠시 지연됨).그러나 탐색은 완료되지 않습니다.또한 로그인하지 않은 경우 다음으로 리디렉션됩니다./login경로입니다. 그래서, 제가 가지고 있는 문제입니다.return true사용자에게 요청한 페이지를 표시하지 않습니다.콜백을 사용하고 있기 때문인 것 같은데, 다른 방법을 찾을 수가 없습니다.무슨 생각 있어요?
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
}
}
있습니다.return그리움과 나는 사용합니다.map()대신에subscribe()왜냐면subscribe()를 반환합니다.Subscription조금도 아닌Observable
를 사용할 수 있습니다.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);
});
}
}
}
canActivate반환할 수 있습니다.Promise그것으로 해결됩니다.boolean너무
약속으로 참/거짓을 반환할 수 있습니다.
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);
}
}
})
})
}
}
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;
}
})
);
}
}
가장 인기 있는 답변에 대해 자세히 설명합니다.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;
});
}
}
참고: 이것은 상당히 단순한 테스트입니다.사용자 인스턴스를 콘솔 로그에 기록하여 사용자의 더 자세한 측면에 대해 테스트할지 여부를 확인할 수 있습니다.하지만 적어도 로그인하지 않은 사용자로부터 경로를 보호하는 데 도움이 되어야 합니다.
다른 구현 방법을 보여주기 위해서입니다.설명서에 따르면, 그리고 다른 답변에서 언급한 대로 CanActivate의 반환 유형은 부울로 해결되는 약속일 수도 있습니다.
참고: 표시된 예제는 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);
}
}
저의 경우 응답 상태 오류에 따라 다른 동작을 처리해야 했습니다.RxJS 6+의 경우 다음과 같이 작동합니다.
@Injectable()
export class AuthGuard implements CanActivate {
constructor(private auth: AngularFireAuth, private router: Router) {}
public canActivate(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<boolean> | boolean {
return this.auth.pipe(
tap({
next: val => {
if (val) {
console.log(val, 'authenticated');
return of(true); // or if you want Observable replace true with of(true)
}
console.log(val, 'acces denied!');
return of(false); // or if you want Observable replace true with of(true)
},
error: error => {
let redirectRoute: string;
if (error.status === 401) {
redirectRoute = '/error/401';
this.router.navigateByUrl(redirectRoute);
} else if (error.status === 403) {
redirectRoute = '/error/403';
this.router.navigateByUrl(redirectRoute);
}
},
complete: () => console.log('completed!')
})
);
}
}
어떤 경우에는 이것이 작동하지 않을 수도 있습니다, 적어도.next연산자의 일부입니다.그것을 제거하고 오래된 상품을 추가합니다.map아래와 같이:
public canActivate(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<boolean> | boolean {
return this.auth.pipe(
map((auth) => {
if (auth) {
console.log('authenticated');
return true;
}
console.log('not authenticated');
this.router.navigateByUrl('/login');
return false;
}),
tap({
error: error => {
let redirectRoute: string;
if (error.status === 401) {
redirectRoute = '/error/401';
this.router.navigateByUrl(redirectRoute);
} else if (error.status === 403) {
redirectRoute = '/error/403';
this.router.navigateByUrl(redirectRoute);
}
},
complete: () => console.log('completed!')
})
);
}
비동기 대기 사용 중...당신은 약속이 해결되기를 기다립니다.
async getCurrentSemester() {
let boolReturn: boolean = false
let semester = await this.semesterService.getCurrentSemester().toPromise();
try {
if (semester['statusCode'] == 200) {
boolReturn = true
} else {
this.router.navigate(["/error-page"]);
boolReturn = false
}
}
catch (error) {
boolReturn = false
this.router.navigate(["/error-page"]);
}
return boolReturn
}
여기에 내 인증 정보가 있습니다(@angular v7.2).
async canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
let security: any = null
if (next.data) {
security = next.data.security
}
let bool1 = false;
let bool2 = false;
let bool3 = true;
if (this.webService.getCookie('token') != null && this.webService.getCookie('token') != '') {
bool1 = true
}
else {
this.webService.setSession("currentUrl", state.url.split('?')[0]);
this.webService.setSession("applicationId", state.root.queryParams['applicationId']);
this.webService.setSession("token", state.root.queryParams['token']);
this.router.navigate(["/initializing"]);
bool1 = false
}
bool2 = this.getRolesSecurity(next)
if (security && security.semester) {
// ---- watch this peace of code
bool3 = await this.getCurrentSemester()
}
console.log('bool3: ', bool3);
return bool1 && bool2 && bool3
}
경로는
{ path: 'userEvent', component: NpmeUserEvent, canActivate: [AuthGuard], data: { security: { semester: true } } },
언급URL : https://stackoverflow.com/questions/38425461/angular2-canactivate-calling-async-function
'codememo' 카테고리의 다른 글
| 한 번의 활동을 만들기 위한 공유 환경설정 (0) | 2023.08.21 |
|---|---|
| __init_.py에서 참조 'xxx'을(를) 찾을 수 없습니다. (0) | 2023.08.21 |
| 전체 응용 프로그램을 세로 모드로만 설정하는 방법은 무엇입니까? (0) | 2023.08.21 |
| Ionic + Angular POST 요청 반환 상태 404 (0) | 2023.08.21 |
| Python에 메서드가 있는지 확인하는 방법은 무엇입니까? (0) | 2023.08.21 |