Компоненты не отображаются после охраны, angular 9 - PullRequest
0 голосов
/ 30 марта 2020

Я пытаюсь защитить аутентифицированные маршруты, используя промежуточное программное обеспечение AuthGuard. Когда я внедряю это промежуточное ПО в маршрут. Эти маршруты не работают после того, как я активирую охрану.

Модуль маршрутизации приложений

const routes: Routes = [
  {
    path: 'posts',
    canLoad: [AuthGuardMiddleware],
    loadChildren: () => import('./modules/posts/posts.module').then(m => m.PostsModule)
  },
  {
    path: 'users',
    canLoad: [AuthGuardMiddleware],
    loadChildren: () => import('./modules/users/users.module').then(m => m.UsersModule)
  }
];

@NgModule({
  imports: [RouterModule.forRoot(routes, {
    preloadingStrategy: PreloadAllModules
  })],
  exports: [RouterModule]
})

и AuthGuardMiddleware

@Injectable({
  providedIn: 'root'
})
export class AuthGuardMiddleware implements CanActivate, CanLoad {
  constructor(private authService: AuthService, private router: Router) {
  }

  canActivate(
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ): Observable<boolean | UrlTree> {
    return this.authService.user.pipe(map(user => {
      if (user) {
        return true;
      }
      return this.router.createUrlTree(['/login']);
    }));
  }

  canLoad(route: Route, segments: UrlSegment[]): Observable<boolean> | Promise<boolean> | boolean {
    return this.authService.user.pipe(map(user => {
      if (user) {
        return true;
      }
      this.router.navigate(['/']);
      return false;
    }));
  }
}

Как это исправить? Примечание: AuthService :: user type имеет тип BehaviorSubject, инициализированный как нулевой отлично работает Я до сих пор не знаю, что именно вызывает эту ошибку.

компонент приложения

export class AppComponent implements OnInit {
  currentUrl: string;
  isAuthRoute = false;

  constructor(private router: Router) {
  }

  ngOnInit() {
    this.router.events.subscribe(event => {
      if (event instanceof NavigationEnd) {
        this.currentUrl = event.url;
        this.isAuthRoute = ['/login', '/register']
          .indexOf(this.currentUrl) !== -1;
      }
    });
  }
}

представление компонента приложения

<div *ngIf="!isAuthRoute">
  <div class="row page-wrapper">
    <div class="col-md-3 col-md-pull-9">
      <app-sidebar></app-sidebar>
    </div>
    <div class="col-md-9 col-md-push-3 content-area">
      <router-outlet></router-outlet>
    </div>
  </div>
</div>

<div style="height: 80vh" class="d-flex justify-content-center align-items-center" *ngIf="isAuthRoute">
  <router-outlet ></router-outlet>
</div>

Ответы [ 2 ]

1 голос
/ 30 марта 2020

Ваш AuthService.user возвращает наблюдаемый поток, и он никогда не завершается. Насколько я знаю, canLoad и canActivate нужно заполнить Observable. Вы можете сделать это, используя оператор take(1):

  canActivate(
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ): Observable<boolean | UrlTree> {
    return this.authService.user.pipe(
       map(user => {
        if (user) {
          return true;
        }
        return this.router.createUrlTree(['/login']);
      }),
      take(1)
    );
  }

  canLoad(route: Route, segments: UrlSegment[]): Observable<boolean> | Promise<boolean> | boolean {
    return this.authService.user.pipe(
      map(user => {
        if (user) {
          return true;
        }
        this.router.navigate(['/']);
        return false;
      }),
      take(1)
    );
  }

Я думаю, еще одна причина, по которой это может произойти, заключается в том, что вы используете стратегию PreloadAllModules. Это немедленно загрузит все модули, но я полагаю, что это происходит, когда пользователь еще не вошел в систему, и поэтому защита вернет false, а модуль не загрузится и не будет повторен.

Итак вам нужно переосмыслить, если вы хотите использовать защиту canLoad таким образом, если вы используете PreloadAllModules. Возможно, защиты canActivate будет достаточно.

Вы также можете реализовать собственную стратегию предварительной загрузки, которая каким-то образом ожидает, когда пользователь войдет в систему, чтобы загрузить ее


С вашей дополнительной информацией о условный маршрутизатор-розетка имеет смысл, потому что сначала компонент будет помещен в один router-outlet, но после завершения маршрутизации другой router-outlet станет видимым, но там ничего не было размещено :). Вы можете обновить свой шаблон, используя директиву ngTemplateOutlet, чтобы обойти это:

<ng-template #outlet>
  <router-outlet ></router-outlet>
</ng-template>

<div *ngIf="!isAuthRoute">
  <div class="row page-wrapper">
    <div class="col-md-3 col-md-pull-9">
      <app-sidebar></app-sidebar>
    </div>
    <div class="col-md-9 col-md-push-3 content-area">
      <ng-component [ngTemplateOutlet]="outlet"></ng-component>
    </div>
  </div>
</div>

<div style="height: 80vh" class="d-flex justify-content-center align-items-center" *ngIf="isAuthRoute">
  <ng-component [ngTemplateOutlet]="outlet"></ng-component>
</div>

Таким образом, вы убедитесь, что в AppComponent помещен только один router-outlet, что и должно быть быть сделано

0 голосов
/ 30 марта 2020

Я не вижу, где вы используете AuthGuard в вашем AppRoutingModule.

Попробуйте применить его к любому маршруту, например:

{
    path: 'posts',
    canLoad: [AuthGuard],
    loadChildren: () => import('./modules/posts/posts.module').then(m => m.PostsModule),
},
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...