0

我没有登录页面,这是 sso 调用

在应用程序组件中,我已经调度了一个动作来加载服务器端令牌调用并获取令牌,并且基于用户角色我可以激活路由中的守卫。如果警卫激活返回 true,我将进入仪表板页面。

在dashboard页面中,我在浏览器URL中进行了刷新,可以在登录动作效果之前激活execute,因此可以激活return false,页面显示空白。

在dashboard有子路由,也有productsdashboard/products等子链接,也有激活的guard,但是可以在login dispatch action影响成功调用之前激活return false。

谁能帮助我我做错了什么?

这里是路由,

  {
    path: '',
    component: HomeComponent,
    canActivate:[AuthGuard],
    children: [
      {
        path: 'product',
        loadChildren: () => productModule
      },
      {
        path: 'order',
        loadChildren: () => orderModule
      }
    ]
  },

这是激活方法:在这里我从效果调用中获得成功,同时从 app.component 调度一个动作:

  canActivate(): Observable<boolean> {
     return this.store.select(appState => appState.auth.isAuthenticated)
      .pipe(map(authUser => {

        if (!authUser) {
          return authUser;
        }
        return authUser;
      }))
    }

应用程序组件:

ngOnInit(){



   this.onSubmit();

}

onSubmit(): void {
  const payload = {
    email: 'test@test.com',
    password: 'admin'
  };
  alert('dispatch an action');
  this.store.dispatch(new LogIn(payload));
}

问题只在页面刷新。单击路由器链接时,逻辑工作正常。

我的初始状态:

export const initialState: State = {
  isAuthenticating:false,
  isAuthenticated: false,
  user: null,
  errorMessage: null
};

流程截图:在此处输入图像描述

4

2 回答 2

4

我可能对此有解决方案。

基本上,您可以在初始状态下设置一个属性以指示您正在初始化:

export interface State {
  isAuthenticated: boolean;
  isInitializing: boolean;
}

const initialState: State = {
  isAuthenticated: false,
  isInitializing: true
}

当您发送登录或注销时,请确保在 reducer 中将 isInitializing 设置为 false:

const _authReducer = createReducer(
  initialState,

  on(AuthActions.setAuthenticated, (state, action) => ({
    ...state,
    isAuthenticated: true,
    isInitializing: false,
  })),

  on(AuthActions.setUnauthenticated, (state, action) => ({
    ...state,
    isAuthenticated: false,
    isInitializing: false,
  }))
);

然后,您可以使用过滤器等待 isInitializing 设置为 false,然后返回有关用户身份验证的信息:

canActivate(
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
    console.log('Authguard running...');

    return this.store.select('auth').pipe(
      map(authState => authState.isInitializing),
      // tap((isInit) => {
      //   console.log('isInit: ' + isInit);
      // }),
      filter((isInit) => !isInit),
      switchMap(() => {
        return this.store.select('auth').pipe(
          map(authState => authState.isAuthenticated)
          // tap((isAuth) => {
          //   console.log('isAuth: ' + isAuth);
          // }),
          map((isAuth) => {
            if (isAuth) return isAuth;
            return this.router.createUrlTree(['/auth']);
          })
        );
      })
    );
  }

如果您想在控制台中监控这些值,您可以从点击运算符中删除评论:)

我使用此解决方案能够在登录时重新加载特定的 url。如果您在未登录时尝试访问同一页面,您将被重定向到登录。

于 2020-09-24T08:35:37.070 回答
0

我认为你的异步有问题。当您刷新页面时,商店应该使用 false 初始化状态,并且在您从后端获得响应之前进行保护检查。有许多可能的解决方案,但根据您公开的代码和防护,我将执行以下操作:

在商店中创建一个标志以了解您是否正在等待身份验证的响应,就像isAuthenticating在您的警卫中那样可以执行以下操作:

canActivate(): Observable<boolean> {
        return new Observable(observer => {
           this.store.select(appState => appState.auth.isAuthenticating)
               .pipe(filter(isAuthenticating => !isAuthenticating))
               .subscribe(() => {
                  this.store.select(appState => appState.auth.isAuthenticated).pipe(
                      take(1)
                  ).subscribe(isAuthenticated => {
                      observer.next(isAuthenticated);
                      observer.complete();
                  })
          })
     }
   }

我希望这有帮助

于 2020-05-02T14:43:50.403 回答