Angular 社交登录(使用 Google)+ Angular 守卫
Angular Social Login (with Google) + Angular Guards
我正在尝试使用 Angular 社交登录 npm 包实现 Angular Guard:
@Injectable({
providedIn: 'root',
})
export class LoginGuard implements CanActivate {
constructor(private router: Router, private authService: SocialAuthService) {}
canActivate(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<boolean> {
console.log('guard');
return this.authService.authState.pipe(
map((socialUser: SocialUser) => {
console.log('map');
return !!socialUser;
}),
catchError((error) => {
console.log(error);
return of(false);
})
);
}
}
我可以看到 guard
正在打印到控制台。但是,我看不到 map
打印到控制台。为什么?
如果我这样做:
@Injectable({
providedIn: 'root',
})
export class LoginGuard implements CanActivate {
constructor(private router: Router, private authService: SocialAuthService) {}
canActivate(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<boolean> {
console.log('guard');
return new Observable<boolean>((subscriber) => {
console.log('subscriber');
subscriber.next(true);
});
}
}
我可以看到 subscriber
正在打印到控制台。
我做错了什么?
我希望能够将此 Guard 添加到路线中。如果用户未登录,它将被重定向到登录页面(我知道我还没有实现该逻辑;我已经尝试过但失败了,因为我似乎没有获得带有值的 Observable?)。请注意,我使用 Google 作为提供者:
@NgModule({
declarations: [
AppComponent,
IndexPageComponent,
SearchPageComponent,
InputKeywordsComponent,
DisplayNewsListComponent,
],
imports: [
BrowserModule,
AppRoutingModule,
ReactiveFormsModule,
HttpClientModule,
SocialLoginModule,
],
providers: [
{
provide: 'SocialAuthServiceConfig',
useValue: {
autoLogin: false,
providers: [
{
id: GoogleLoginProvider.PROVIDER_ID,
provider: new GoogleLoginProvider(
'superVerySecret'
),
},
],
} as SocialAuthServiceConfig,
},
],
bootstrap: [AppComponent],
})
export class AppModule {}
以及路由模块:
const routes: Routes = [
{ path: '', component: IndexPageComponent },
{ path: 'search', component: SearchPageComponent, canActivate: [LoginGuard] },
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule],
providers: [LoginGuard]
})
export class AppRoutingModule {}
PS1: 我可以正常登录
PS2:
- @angular/core@12.2.13
- @rxjs@6.6.7
- angularx-social-login@4.0.1
您的地图前需要一个 take(1)
,以获得 this.authService.authState
的最新值,即:
@Injectable({
providedIn: 'root',
})
export class LoginGuard implements CanActivate {
constructor(private router: Router, private authService: SocialAuthService) {}
canActivate(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<boolean> {
console.log('guard');
return this.authService.authState.pipe(
take(1), // <--- add this line
map((socialUser: SocialUser) => {
console.log('map');
return !!socialUser;
}),
catchError((error) => {
console.log(error);
return of(false);
})
);
}
}
感谢 @msmiechowski for helping me reaching a solution in this GitHub 问题。
我的解决方案:
// login.guard.ts
@Injectable({
providedIn: 'root',
})
export class LoginGuard implements CanActivate {
constructor(private router: Router, private loginService: LoginService) {}
canActivate(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<boolean> {
if (this.loginService.checkAuthState()) {
return of(true);
} else {
this.router.navigateByUrl('/');
return of(false);
}
}
}
// login.service.ts
// ...
checkAuthState(): boolean {
let flag = false;
this.authService.authState.subscribe({
next: (socialUser: SocialUser) => {
if (socialUser) {
flag = true;
}
},
error: (error) => {
console.log(error);
},
complete: () => {
console.log('Complete!');
},
});
return flag;
}
// ...
我正在尝试使用 Angular 社交登录 npm 包实现 Angular Guard:
@Injectable({
providedIn: 'root',
})
export class LoginGuard implements CanActivate {
constructor(private router: Router, private authService: SocialAuthService) {}
canActivate(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<boolean> {
console.log('guard');
return this.authService.authState.pipe(
map((socialUser: SocialUser) => {
console.log('map');
return !!socialUser;
}),
catchError((error) => {
console.log(error);
return of(false);
})
);
}
}
我可以看到 guard
正在打印到控制台。但是,我看不到 map
打印到控制台。为什么?
如果我这样做:
@Injectable({
providedIn: 'root',
})
export class LoginGuard implements CanActivate {
constructor(private router: Router, private authService: SocialAuthService) {}
canActivate(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<boolean> {
console.log('guard');
return new Observable<boolean>((subscriber) => {
console.log('subscriber');
subscriber.next(true);
});
}
}
我可以看到 subscriber
正在打印到控制台。
我做错了什么?
我希望能够将此 Guard 添加到路线中。如果用户未登录,它将被重定向到登录页面(我知道我还没有实现该逻辑;我已经尝试过但失败了,因为我似乎没有获得带有值的 Observable?)。请注意,我使用 Google 作为提供者:
@NgModule({
declarations: [
AppComponent,
IndexPageComponent,
SearchPageComponent,
InputKeywordsComponent,
DisplayNewsListComponent,
],
imports: [
BrowserModule,
AppRoutingModule,
ReactiveFormsModule,
HttpClientModule,
SocialLoginModule,
],
providers: [
{
provide: 'SocialAuthServiceConfig',
useValue: {
autoLogin: false,
providers: [
{
id: GoogleLoginProvider.PROVIDER_ID,
provider: new GoogleLoginProvider(
'superVerySecret'
),
},
],
} as SocialAuthServiceConfig,
},
],
bootstrap: [AppComponent],
})
export class AppModule {}
以及路由模块:
const routes: Routes = [
{ path: '', component: IndexPageComponent },
{ path: 'search', component: SearchPageComponent, canActivate: [LoginGuard] },
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule],
providers: [LoginGuard]
})
export class AppRoutingModule {}
PS1: 我可以正常登录
PS2:
- @angular/core@12.2.13
- @rxjs@6.6.7
- angularx-social-login@4.0.1
您的地图前需要一个 take(1)
,以获得 this.authService.authState
的最新值,即:
@Injectable({
providedIn: 'root',
})
export class LoginGuard implements CanActivate {
constructor(private router: Router, private authService: SocialAuthService) {}
canActivate(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<boolean> {
console.log('guard');
return this.authService.authState.pipe(
take(1), // <--- add this line
map((socialUser: SocialUser) => {
console.log('map');
return !!socialUser;
}),
catchError((error) => {
console.log(error);
return of(false);
})
);
}
}
感谢 @msmiechowski for helping me reaching a solution in this GitHub 问题。
我的解决方案:
// login.guard.ts
@Injectable({
providedIn: 'root',
})
export class LoginGuard implements CanActivate {
constructor(private router: Router, private loginService: LoginService) {}
canActivate(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<boolean> {
if (this.loginService.checkAuthState()) {
return of(true);
} else {
this.router.navigateByUrl('/');
return of(false);
}
}
}
// login.service.ts
// ...
checkAuthState(): boolean {
let flag = false;
this.authService.authState.subscribe({
next: (socialUser: SocialUser) => {
if (socialUser) {
flag = true;
}
},
error: (error) => {
console.log(error);
},
complete: () => {
console.log('Complete!');
},
});
return flag;
}
// ...