Когда вызывается моя защита аутентификации, она на короткое время отображает страницу входа при перезагрузке страницы по маршруту с canActivate - Angular v17

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

ТокенСервис

export class TokenService {
  isAuthentications: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
  constructor(@Inject(PLATFORM_ID) private platformId: Object) { 
    const token = this.getToken();
    if (token){
      this.updateToken(true)
    }
  }

  setToken(token: string){
    this.updateToken(true);
    localStorage.setItem('user', token)
  }
  updateToken(status: boolean){
    this.isAuthentications.next(status)
  }
  getToken(): string | null{
    if (typeof window !== 'undefined' && window.sessionStorage) {
      return localStorage.getItem('user');
    }

    return null
  }
}

Аутгард

export const authGuard: CanActivateFn = (route, state) =\> {
const tokenService = inject(TokenService)
const router = inject(Router)
// tokenService.isAuthentications.subscribe({
//   next: (v) =\> {
//     if (!v){
//         router.navigate(['/login'])
//     }
//   }
// })
// return true;

return tokenService.isAuthentications.pipe(map( (user) =\> {
if (!user){
return router.createUrlTree(['/login']);
}else{
return true
}
}))
};
Routes
export const routes: Routes = [
  { path: 'login', component: LoginComponent },
  { path: '', redirectTo: 'login', pathMatch: 'full'},
  {path: '' , component: LayoutComponent, children: [
    {path: 'dashboard', component: DashboardComponent, canActivate: [authGuard]  }
  ]}
];

гифка, показывающая проблему

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

Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Angular и React для вашего проекта веб-разработки?
Angular и React для вашего проекта веб-разработки?
Когда дело доходит до веб-разработки, выбор правильного front-end фреймворка имеет решающее значение. Angular и React - два самых популярных...
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Мы провели Twitter Space, обсудив несколько проблем, связанных с последними дополнениями в Angular. Также прошла Angular Tiny Conf с 25 докладами.
Угловой продивер
Угловой продивер
Оригинал этой статьи на турецком языке. ChatGPT используется только для перевода на английский язык.
Мое недавнее углубление в Angular
Мое недавнее углубление в Angular
Недавно я провел некоторое время, изучая фреймворк Angular, и я хотел поделиться своим опытом со всеми вами. Как человек, который любит глубоко...
Освоение Observables и Subjects в Rxjs:
Освоение Observables и Subjects в Rxjs:
Давайте начнем с основ и постепенно перейдем к более продвинутым концепциям в RxJS в Angular
1
0
107
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Проблема связана с включением SSR, поскольку на сервере нет window или localStorage. Страница входа генерируется на сервере и отправляется во внешний интерфейс. Непосредственно перед повторным запуском пользовательского интерфейса (думаю, гидратация!) Мы видим вспышку страницы входа в систему.

Чтобы решить эту проблему, все, что вам нужно сделать, это сделать так, чтобы страница входа в систему ничего не показывала, когда она создается на сервере, и тогда создается впечатление, что приложение загружается. В качестве альтернативы вы также можете показать заставку с загрузчиком на странице входа в систему, когда режим сервера, это избавит от этой ошибки.

ТС:

...
export class LoginComponent {
  isUser = signal(false)
  isServer = false;
  
  constructor(private auth: AuthService, private router: Router, private tokenService: TokenService, 
    @Inject(PLATFORM_ID) platformId: Object){
      this.isServer = isPlatformServer(platformId);
    console.info('aqui')
    const userToken = this.tokenService.getToken()
    if (userToken){
      this.isUser.set(true)
    }
  }
  ...

HTML:

@if (!this.isUser() && !isServer) {
    <p>login works!</p>
<button mat-raised-button (click) = "login()"> LOGIN </button>
}

Репозиторий GitHub


Пример спиннера

HTML

@if (isServer) {
    <div style = "height:100vh;width:100vw;background-color: rgb(194, 24, 91); display: flex; align-items: center; justify-content: center;">
        <div id = "loading"></div>
    </div>
} @else {
    @if (!this.isUser()) {
        <p>login works!</p>
    <button mat-raised-button (click) = "login()"> LOGIN </button>
    }
}

CSS

#loading {
  display: inline-block;
  width: 50px;
  height: 50px;
  border: 3px solid rgba(255,255,255,.3);
  border-radius: 50%;
  border-top-color: #fff;
  animation: spin 1s ease-in-out infinite;
  -webkit-animation: spin 1s ease-in-out infinite;
}

@keyframes spin {
  to { -webkit-transform: rotate(360deg); }
}
@-webkit-keyframes spin {
  to { -webkit-transform: rotate(360deg); }
}

ТС:

export class LoginComponent {
  isServer = false;
  isUser = signal(false)

  constructor(
    private auth: AuthService, 
    private router: Router, 
    private tokenService: TokenService,
    @Inject(PLATFORM_ID) platformId: Object){
      this.isServer = isPlatformServer(platformId);
    console.info('aqui')
    const userToken = this.tokenService.getToken()
    if (userToken){
      this.isUser.set(true)
    }
  }

Репозиторий GitHub

Это еще не решило проблему. Я добавил APP_INITIALIZER в качестве поставщика и проверил, установлено ли для моего TokenService значение @Injectable({ ProvideIn: 'root' })

Camilo 15.05.2024 17:52

@Camilo, не могли бы вы поделиться репозиторием GitHub для отладки?

Naren Murali 15.05.2024 17:56

конечно, вот оно -> github.com/CamilodeAssis/new-manager

Camilo 15.05.2024 18:45

@Camilo обновил мой ответ! спасибо за рабочий пример!

Naren Murali 15.05.2024 19:07

Другие вопросы по теме

ASP.NET Core 8 Blazor: OpenIdConnect сохраняет область действия пользователя в базе данных приложения
Моя пользовательская страница входа перенаправляется в цикле после обновления до Spring Security 6
Маршрут «[...nextauth]/route.ts» не соответствует требуемым типам маршрута Next.js. Неверная конфигурация «GET»:
Серверное приложение Blazor с проверкой подлинности Windows получает ошибку 401 неавторизованно
Какой режим аутентификации для программной загрузки файлов в корзину S3
Cypress — (неперехваченное исключение) NotSupportedError: пользовательский агент не поддерживает учетные данные открытого ключа
Аутентификация с помощью Go Router и BLoC во флаттере
Выход пользователя из нескольких поддоменов с помощью внешнего интерфейса PKCE
Исправьте HTML-код, чтобы включить автозаполнение ввода TOTP менеджерами паролей
Пользовательское промежуточное ПО ASP.NET после авторизации/аутентификации