Защита маршрутов

FAST Element — это современная библиотека для создания веб-компонентов на основе стандарта Web Components. Она позволяет строить интерактивные интерфейсы с использованием декларативного подхода, реактивных свойств и шаблонов. В контексте SPA (Single Page Application) или приложений с маршрутизацией возникает необходимость контролировать доступ к определённым маршрутам.

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


Реактивные свойства и наблюдатели

FAST Element использует реактивные свойства, определяемые через декоратор @attr или через статический объект properties. Эти свойства автоматически обновляют DOM при изменении значения и могут быть использованы для контроля доступа.

Пример:

import { FASTElement, html, css, observable } from "@microsoft/fast-element";

class ProtectedPage extends FASTElement {
  @observable userRole;

  connectedCallback() {
    super.connectedCallback();
    this.checkAccess();
  }

  checkAccess() {
    if (this.userRole !== 'admin') {
      this.redirectToLogin();
    }
  }

  redirectToLogin() {
    window.history.pushState({}, '', '/login');
    window.dispatchEvent(new PopStateEvent('popstate'));
  }
}

ProtectedPage.define({
  name: 'protected-page',
  template: html`<div>Контент доступен только для администратора</div>`,
  styles: css`div { color: red; }`
});

В данном примере свойство userRole реактивно отслеживает роль пользователя, и при отсутствии нужной роли выполняется редирект.


Условный рендеринг

FAST Element поддерживает условное отображение через директивы if и repeat. Для защиты маршрутов условное отображение позволяет скрывать контент, если пользователь не имеет прав.

import { html, FASTElement } from "@microsoft/fast-element";

class DashboardPage extends FASTElement {
  userRole = 'guest';
}

DashboardPage.define({
  name: 'dashboard-page',
  template: html`
    ${x => x.userRole === 'admin' ? html`<div>Админская панель</div>` : html`<div>Доступ запрещён</div>`}
  `
});

В этом примере содержимое компонента отображается только для пользователя с ролью admin. Для остальных пользователей показывается сообщение о запрете доступа.


Интеграция с маршрутизатором

В SPA на основе FAST Element маршрутизация чаще всего строится с использованием сторонних библиотек, например Navigo или Vaadin Router. Защита маршрутов реализуется на уровне хуков маршрутизатора или функции, проверяющей состояние пользователя.

Пример с Vaadin Router:

import { Router } from '@vaadin/router';

const router = new Router(document.getElementById('outlet'));

router.setRoutes([
  { path: '/', component: 'home-page' },
  { path: '/login', component: 'login-page' },
  { path: '/dashboard', component: 'dashboard-page', action: (context, commands) => {
      const userRole = getUserRole();
      if (userRole !== 'admin') {
        return commands.redirect('/login');
      }
      return undefined;
  }}
]);

Хук action выполняется перед загрузкой компонента. Если пользователь не имеет нужной роли, происходит редирект на страницу входа.


Управление состоянием пользователя

Для эффективной защиты маршрутов важно централизованно хранить информацию о пользователе и его правах. Это может быть реализовано через глобальный объект состояния или реактивный store.

export const userStore = {
  userRole: 'guest',
  observers: [],
  
  setRole(role) {
    this.userRole = role;
    this.observers.forEach(fn => fn(role));
  },

  subscribe(fn) {
    this.observers.push(fn);
  }
};

Компоненты могут подписываться на изменения роли и автоматически проверять доступ:

import { FASTElement, html } from "@microsoft/fast-element";
import { userStore } from './user-store.js';

class ProtectedComponent extends FASTElement {
  connectedCallback() {
    super.connectedCallback();
    userStore.subscribe(role => this.checkAccess(role));
  }

  checkAccess(role) {
    if (role !== 'admin') {
      window.history.pushState({}, '', '/login');
      window.dispatchEvent(new PopStateEvent('popstate'));
    }
  }
}

Асинхронная проверка прав доступа

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

async connectedCallback() {
  super.connectedCallback();
  const hasAccess = await this.verifyAccess();
  if (!hasAccess) {
    this.redirectToLogin();
  }
}

async verifyAccess() {
  const response = await fetch('/api/check-role');
  const data = await response.json();
  return data.role === 'admin';
}

Резюме ключевых механизмов защиты маршрутов

  • Реактивные свойства и наблюдатели позволяют динамически изменять поведение компонента на основе состояния пользователя.
  • Условный рендеринг скрывает или отображает контент в зависимости от прав.
  • Маршрутизаторы с хуками дают возможность блокировать маршруты до загрузки компонента.
  • Глобальное состояние пользователя обеспечивает централизованный контроль прав.
  • Асинхронные проверки интегрируют серверные данные для безопасного доступа.

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