Защита angular2 не работает при обновлении страницы

Перед каждым запросом я хочу убедиться, что профиль пользователя доступен. Для этого я использую охрану canActivateChild.

Согласно документации angular2 можно вернуть наблюдаемое: https://angular.io/api/router/CanActivateChild

app.routes.ts

export const routes: Routes = [
  {
    path: '',
    canActivateChild: [ProfileGuard],
    children: [
      {
        path: 'home',
        component: HomeComponent,
        canActivate: [AuthGuard]
      },
      {
        path: 'login',
        component: LoginComponent,
        canActivate: [GuestGuard]
      },
 }
];

canActivatedChild выполняется перед дочерним маршрутом canActivate

профиль.guard.ts:

export class ProfileGuard implements CanActivateChild {

  constructor(private profileService: ProfileService, private snackbar: MdSnackBar) { }

  canActivateChild(childRoute: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean | Observable<boolean>  {

    if (this.profileService.user == null && localStorage.getItem('__token') != null) {
      return this.profileService.loadProfile().map((user) => {
        console.log('profile loaded');
        this.profileService.user = <UserModel>user.data;
        return true;
      });
    }
    return true;
  }

}

Функция профиля нагрузки:

  public loadProfile(): Observable<any> {
    console.log('load');
    return this.http.get('/profile').map(res => res.json());
  }

Когда я перемещаюсь по меню (<a> с routeLink), console.log('profile loaded') работает. Но если я перезагружаю страницу с помощью f5 или через браузер, он никогда не попадает туда.

console.log('load') всегда выполняется.

ИЗМЕНИТЬ:

Если я в canActivateChild вернусь:

return Observable.of(true).map(() => {
  console.log('Test');
  return true;
});

Он отлично работает... Я получаю console.log('test')


person Rick Lenes    schedule 22.07.2017    source источник
comment
В консоли браузера F12 на вкладке сети вы видите запрос к /profile и он успешен?   -  person Hendrik Brummermann    schedule 22.07.2017
comment
Это интересная проблема. Будет ли все работать так, как ожидалось, если вы просто вернете Observable.of(true) вместо вызова this.profileService.loadProfile()?   -  person BeetleJuice    schedule 22.07.2017
comment
Можете ли вы попробовать plnkr, если это возможно, так вы получите помощь очень быстро. Вы можете использовать фиктивные данные для вызовов HTTP   -  person Vamshi    schedule 22.07.2017
comment
@HendrikBrummermann Да, запрос сделан, а также успешно с правильными данными   -  person Rick Lenes    schedule 22.07.2017
comment
Если вы console.log из canActivateChild() (не из самой цепочки Observable), это сработает?   -  person BeetleJuice    schedule 22.07.2017
comment
@BeetleJuice Да, это работает .. Итак, он выполняет код в canActivateChild(), а Observable.of(true) работает, как и ожидалось, в первый раз я ошибся   -  person Rick Lenes    schedule 22.07.2017
comment
Вы уверены в своем утверждении if? Я думаю, вам нужно проверить это, напишите console.log(test) перед if.   -  person Hasan Beheshti    schedule 23.07.2017
comment
возможно, это из-за this.profileService.user == null, когда вы перезагружаете страницу с помощью F5, эта переменная будет нулевой, и если ваш localStorage.getItem(__token) был нулевым, эта проблема будет происходить   -  person Hasan Beheshti    schedule 23.07.2017
comment
@HasanBeheshti Я уже проверил это, проблема не в этом. И если я смотрю во вкладке сети f12, то я вижу, что запрос сделан и успешно   -  person Rick Lenes    schedule 24.07.2017


Ответы (2)


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

import {Observable, ReplaySubject} from 'rxjs/Rx';

public loadProfile(): Observable<any> {
  console.log('loading profile');
  return this.http.get('/profile').map(res => res.json());
}

public isUserLoggedInObs(): Observable<boolean> {
  const userLoggedIn: ReplaySubject<boolean> = new ReplaySubject<boolean>;
  this.loadProfile.first().subscribe(
     user => userLoggedIn.next(user.loggedIn === true)
  )
  return userLoggedIn.asObservable();
}


canActivateChild(childRoute: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean | Observable<boolean>  {
   return this.profileService.isUserLoggedInObs()
}
person Daniel Swiegers    schedule 13.09.2017

Я работал на RC @angular/router. После того, как я обновил это, он работал, как и ожидалось.

person Rick Lenes    schedule 07.10.2017