Angular Guard配合Angular Social Login谷歌登录时authState管道不触发
问题根因
核心问题来自angularx-social-login的authState流特性和你的配置项autoLogin: false的组合:
authState是仅在登录/登出动作触发、登录状态变更时才会发射新值的流,当你配置autoLogin: false时,应用初始化阶段不会主动校验本地存储的历史登录态,也不会给authState发射初始值- 守卫触发时如果还没有执行过登录/登出操作,
authState不会发射任何值,守卫会一直处于等待返回结果的挂起状态,自然不会执行pipe内的map回调
你自定义的Observable可以正常工作,是因为你在订阅回调内主动调用了subscriber.next(true)发射了值,守卫拿到返回值后可以正常执行后续路由逻辑。
解决方案
方案1:保留autoLogin: false配置,主动触发登录态校验
在守卫内先调用signInSilently主动触发静默登录校验,触发authState发射当前的登录状态,同时添加take(1)取第一个值后结束订阅,避免流长期挂起:
@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.signInSilently() .pipe( switchMap(() => this.authService.authState), take(1), map((socialUser: SocialUser) => { console.log('map'); const isLoggedIn = !!socialUser; if (!isLoggedIn) { // 未登录跳转到首页,可替换为你的登录页路径 this.router.navigate(['/']); } return isLoggedIn; }), catchError((error) => { console.log(error); // 静默登录失败(无有效登录态)跳转首页 this.router.navigate(['/']); return of(false); }) ); } }
方案2:开启autoLogin,简化守卫逻辑
如果你希望应用启动时自动校验本地登录态,可以直接修改AppModule的配置,将autoLogin设为true,这样authState在应用初始化时就会主动发射初始登录状态:
// AppModule配置修改 providers: [ { provide: 'SocialAuthServiceConfig', useValue: { autoLogin: true, // 改为此值 providers: [ { id: GoogleLoginProvider.PROVIDER_ID, provider: new GoogleLoginProvider('superVerySecret'), }, ], } as SocialAuthServiceConfig, }, ]
对应的守卫代码可以简化为:
@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), map((socialUser: SocialUser) => { console.log('map'); const isLoggedIn = !!socialUser; if (!isLoggedIn) this.router.navigate(['/']); return isLoggedIn; }), catchError((error) => { console.log(error); this.router.navigate(['/']); return of(false); }) ); } }
内容的提问来源于stack exchange,提问作者doublethink13
相关产品推荐
相关产品推荐

