在页面刷新中:ngrx 存储调度问题与守卫 canactivate

Moh*_*hir 1 ngrx-effects angular ngrx-store-4.0 angular-guards angular-ngrx-data

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

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

在仪表板页面中,我在浏览器 URL 中有一个刷新,可以激活在登录操作效果之前执行,因此可以激活返回 false 且页面显示空白。

在仪表板中有子路由,也有一些子链接,例如产品仪表板/产品,也有激活的防护,但可以在登录调度操作影响成功调用之前激活返回 false。

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

这里是路由,

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

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

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

        if (!authUser) {
          return authUser;
        }
        return authUser;
      }))
    }
Run Code Online (Sandbox Code Playgroud)

应用程序组件:

ngOnInit(){



   this.onSubmit();

}

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

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

我的初始状态:

export const initialState: State = {
  isAuthenticating:false,
  isAuthenticated: false,
  user: null,
  errorMessage: null
};
Run Code Online (Sandbox Code Playgroud)

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

小智 6

我可能有一个解决方案。

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

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

const initialState: State = {
  isAuthenticated: false,
  isInitializing: true
}
Run Code Online (Sandbox Code Playgroud)

当您调度登录或注销时,请确保在减速器中将 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,
  }))
);
Run Code Online (Sandbox Code Playgroud)

然后,在您的防护中,您可以使用过滤器等待 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']);
          })
        );
      })
    );
  }
Run Code Online (Sandbox Code Playgroud)

如果您想在控制台中监视这些值,您可以删除点击运算符中的注释:)

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