Проблема в основном заключается в том, что когда я вхожу в панель управления, каждый раз, когда я перезагружаю страницу браузера, он на мгновение отображает компонент входа в систему.
ТокенСервис
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] }
]}
];
Я пробовал и другие подходы к обеспечению безопасности маршрута, однако всякий раз, когда мой охранник должен перенаправить на «войти», он ведет себя следующим образом.
Проблема связана с включением 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)
}
}
...
@if (!this.isUser() && !isServer) {
<p>login works!</p>
<button mat-raised-button (click) = "login()"> LOGIN </button>
}
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)
}
}
@Camilo, не могли бы вы поделиться репозиторием GitHub для отладки?
конечно, вот оно -> github.com/CamilodeAssis/new-manager
@Camilo обновил мой ответ! спасибо за рабочий пример!
Это еще не решило проблему. Я добавил APP_INITIALIZER в качестве поставщика и проверил, установлено ли для моего TokenService значение @Injectable({ ProvideIn: 'root' })