Защищенные маршруты и авторизация

Защищенные маршруты (protected routes) в приложениях на Preact используются для ограничения доступа к определенным страницам или компонентам в зависимости от состояния авторизации пользователя. Это ключевой элемент безопасности и управления доступом в одностраничных приложениях (SPA).

В Preact маршрутизация обычно реализуется с использованием библиотеки preact-router, которая обеспечивает управление переходами между компонентами на основе URL.

import { h } from 'preact';
import { Router } from 'preact-router';
import Home from './Home';
import Dashboard from './Dashboard';
import Login from './Login';

Создание компонента защищенного маршрута

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

import { h } from 'preact';
import { route } from 'preact-router';

function ProtectedRoute({ component: Component, isAuthenticated, ...props }) {
    if (!isAuthenticated) {
        route('/login', true);
        return null;
    }
    return <Component {...props} />;
}

export default ProtectedRoute;

Пояснения:

  • component: Component — компонент, который должен быть защищен.
  • isAuthenticated — булевый флаг, определяющий состояние авторизации.
  • route('/login', true) — программное перенаправление пользователя на страницу входа, где второй аргумент true означает замену истории браузера.

Интеграция защищенных маршрутов в приложение

Защищенные маршруты подключаются к маршрутизатору аналогично обычным, но оборачиваются в компонент ProtectedRoute.

<Router>
    <Home path="/" />
    <Login path="/login" />
    <ProtectedRoute path="/dashboard" component={Dashboard} isAuthenticated={user.isLoggedIn} />
</Router>

Особенности:

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

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

Для контроля авторизации удобно использовать глобальное состояние приложения. В Preact это можно реализовать через контекст (createContext) или внешние менеджеры состояния (Redux, Zustand).

import { h, createContext } from 'preact';
import { useState } from 'preact/hooks';

export const AuthContext = createContext();

export function AuthProvider({ children }) {
    const [isLoggedIn, setIsLoggedIn] = useState(false);

    const login = () => setIsLoggedIn(true);
    const logout = () => setIsLoggedIn(false);

    return (
        <AuthContext.Provider value={{ isLoggedIn, login, logout }}>
            {children}
        </AuthContext.Provider>
    );
}

Использование контекста в защищенном маршруте:

import { useContext } from 'preact/hooks';
import { AuthContext } from './AuthProvider';
import ProtectedRoute from './ProtectedRoute';
import Dashboard from './Dashboard';

function AppRoutes() {
    const { isLoggedIn } = useContext(AuthContext);

    return (
        <Router>
            <ProtectedRoute path="/dashboard" component={Dashboard} isAuthenticated={isLoggedIn} />
        </Router>
    );
}

Роль токенов и хранение сессии

В реальных приложениях авторизация часто строится на основе токенов (JWT). Токен может храниться в localStorage или sessionStorage, а состояние isAuthenticated вычисляться на его основе.

const token = localStorage.getItem('authToken');
const isLoggedIn = Boolean(token);

Совет по безопасности: хранение токена в localStorage делает его доступным для XSS-атак. Более безопасный вариант — хранение в HTTP-only cookies, обработка которых производится на серверной стороне.

Программное перенаправление после авторизации

После успешного входа в систему пользователь должен быть перенаправлен на защищенный маршрут:

function loginHandler() {
    // логика аутентификации
    localStorage.setItem('authToken', token);
    route('/dashboard', true);
}

Динамические маршруты и защита параметров

Если защищенные страницы используют параметры URL, их также можно безопасно проверять:

<ProtectedRoute
    path="/profile/:userId"
    component={Profile}
    isAuthenticated={isLoggedIn}
/>

В компоненте Profile можно дополнительно проверять, соответствует ли userId текущему пользователю, чтобы избежать несанкционированного доступа.

Обработка ошибок и fallback

Важный аспект — управление ошибками и состояние fallback, когда пользователь не авторизован. Можно отобразить страницу с информацией о необходимости входа или временно показать заглушку:

function ProtectedRoute({ component: Component, isAuthenticated, ...props }) {
    if (!isAuthenticated) {
        return <div>Доступ запрещен. Пожалуйста, войдите в систему.</div>;
    }
    return <Component {...props} />;
}

Вывод

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