首页 > 解决方案 > 在 Angular 8 中谷歌登录后如何重定向到上一页?

问题描述

在Angular8中谷歌登录后如何重定向到上一页?

我将当前 URL 保存在 localStorage 中,并在用户成功登录时使用它来导航。但它不是导航。

这是我的具有登录功能的 AuthService。

export class AuthService {

  constructor(private afAuth: AngularFireAuth , private route: ActivatedRoute) {}

  login() {
    let returnUrl = this.route.snapshot.queryParamMap.get('returnUrl') || '/';
    localStorage.setItem('returnUrl', returnUrl);
    this.afAuth.auth.signInWithRedirect(new firebase.auth.GoogleAuthProvider());
  }

}

这是我的 AuthGuardService

export class AuthGuardService implements CanActivate {
  constructor(private auth: AuthService, public router: Router) {}

  canActivate(route, state: RouterStateSnapshot) {
    return this.auth.user$.pipe(map(user => {
      if (user) { return false; }

      this.router.navigate(['/login'], { queryParams : {returnUrl : state.url}});
      return true;
    }));
  }
}

我正在使用 app.component.ts 导航到上一页。

export class AppComponent {
  constructor(private auth: AuthService, router: Router) {

    auth.user$.subscribe(user => {
      if(user){
        let returnUrl = localStorage.getItem('returnUrl');
        router.navigate([returnUrl]);
      }
    });
  }

}

这是我定义路由的 app.module.ts。

RouterModule.forRoot([
      { path: "", component: HomeComponent },
      { path: "check-out", component: CheckOutComponent, canActivate: [AuthGuardService]  },

       //...

    ])

我正在尝试从地址栏访问“结帐”页面。然后它会根据需要重定向到登录页面。(当用户未登录并且当用户尝试访问“签出”页面时,它会指向登录页面。)我的 URL 看起来像这样带有路由器参数。

http://localhost:4200/login?returnUrl=%2Fcheck-out

但登录后,它不会重定向回“结帐”页面。

用户登录后,我的 URI 如下所示

http://localhost:4200/login?returnUrl=%2Fcheck-out

它没有改变。但在 app.component.ts 我试图导航。

我找不到为什么在用户成功登录后没有导航回“结帐”页面。

标签: angularangular-ui-routergoogle-signinangular-social-login

解决方案


经过一整天的努力,这是我的解决方案。

为所有 url 操作创建一个服务:

import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class PreviousRouteService {

  public setPreviousUrl(url: string) {
    sessionStorage.setItem('previousUrl', url);
  }

  public getPreviousUrl() {
    const previousUrl = sessionStorage.getItem('previousUrl');
    return previousUrl;
  }

  public deletePreviousUrlKey() {
    sessionStorage.removeItem('previousUrl');
  }
}

回到你的警惕,如果他们没有登录,使用 state.url 来获取他们试图去的 url 并保存它:

// save the route
this.previousRouteService.setPreviousUrl(state.url);

像以前一样使用 signInWithRedirect :

this.afAuth.auth.signInWithRedirect(new firebase.auth.GoogleAuthProvider());

请注意,在 AF 6 中,额外的 .auth 被删除,所以看起来像:

this.afAuth.signInWithRedirect(new firebase.auth.GoogleAuthProvider());

signInWithRedirect 完成后,您将被送回您原来的地方。我无法从您的代码中完全看出,但我假设那是登录页面。所以在构造函数中的那个登录页面上(再次注意我已经为 AF 6 删除了额外的 .auth):

this.userSub = this.afAuth.authState.subscribe((user: firebase.User) => {
    this.loggedIn = !!user;
    this.user = user;
    const previousRoute = this.previousRouteService.getPreviousUrl();
    if (previousRoute) {
      this.router.navigate([previousRoute]).then(() => {
        // now reset so don't keep going back if coming to login page
        // put some time otherwise it will delete it before above is finished
        //   even though that shouldn't be the case...
        setTimeout(() => {
          this.previousRouteService.deletePreviousUrlKey();
        }, 8500);
      });
    }
  });

我敢肯定,这不是最优雅的解决方案,但它确实有效。我真的不知道为什么在上一条路线导航到之后 setTimeout 是必要的 - 如果它还没有完成,那么有什么意义呢?或者可能与 authState 的工作和发射方式有关,不知道,但也许更好的工程师可以解释。无论如何,你去。


推荐阅读