Аутентификация и авторизация

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


Основы аутентификации

Аутентификация — процесс проверки личности пользователя. В Preact аутентификация обычно строится вокруг взаимодействия с сервером через API и хранения полученных данных в клиентском состоянии.

Простейший пример аутентификации с использованием fetch и хуков Preact:

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

function LoginForm() {
    const [email, setEmail] = useState('');
    const [password, setPassword] = useState('');
    const [error, setError] = useState('');

    const handleLogin = async () => {
        try {
            const response = await fetch('/api/login', {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ email, password })
            });

            if (!response.ok) throw new Error('Неверные данные');

            const data = await response.json();
            localStorage.setItem('authToken', data.token);
        } catch (err) {
            setError(err.message);
        }
    };

    return (
        <div>
            <input type="email" value={email} onIn put={e => setEmail(e.target.value)} />
            <input type="password" value={password} onIn put={e => setPassword(e.target.value)} />
            <button onCl ick={handleLogin}>Войти</button>
            {error && <p>{error}</p>}
        </div>
    );
}

Ключевые моменты:

  • Использование useState для хранения данных формы и ошибок.
  • Отправка POST-запроса на сервер для проверки учетных данных.
  • Сохранение токена в localStorage или sessionStorage для последующих запросов.

Авторизация и защита маршрутов

Авторизация определяет, к каким ресурсам или действиям пользователь имеет доступ. В Preact маршруты обычно защищаются с помощью оберток (Higher-Order Components) или условного рендеринга.

Пример защищенного маршрута:

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

function ProtectedRoute({ component: Component }) {
    const token = localStorage.getItem('authToken');
    return token ? <Component /> : <LoginForm />;
}

function App() {
    return (
        <Router>
            <Home path="/" />
            <ProtectedRoute path="/dashboard" component={Dashboard} />
        </Router>
    );
}

Особенности реализации:

  • Проверка токена перед отображением защищённого компонента.
  • Возможность перенаправления на форму входа при отсутствии токена.
  • Инкапсуляция логики авторизации в отдельный компонент для повторного использования.

Работа с токенами и сессиями

Для безопасной аутентификации часто используют JWT (JSON Web Token). Токен содержит закодированную информацию о пользователе и может проверяться на сервере. В Preact его удобно хранить в localStorage, sessionStorage или в памяти через контекст.

Пример использования контекста для глобального состояния аутентификации:

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

const AuthContext = createContext();

export function AuthProvider({ children }) {
    const [token, setToken] = useState(localStorage.getItem('authToken'));

    const login = (newToken) => {
        setToken(newToken);
        localStorage.setItem('authToken', newToken);
    };

    const logout = () => {
        setToken(null);
        localStorage.removeItem('authToken');
    };

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

export function useAuth() {
    return useContext(AuthContext);
}

Использование этого контекста позволяет компонентам приложения легко получать данные о текущем пользователе и управлять процессом аутентификации без дублирования кода.


Интеграция с внешними провайдерами

Preact позволяет интегрироваться с внешними системами аутентификации, такими как OAuth2 и OpenID Connect. Обычно это делается через редиректы на сервис провайдера и получение токена в callback URL.

Пример базовой интеграции с OAuth2:

const handleOAuthLogin = () => {
    window.location.href = 'https://auth.example.com/oauth/authorize?client_id=CLIENT_ID&redirect_uri=http://localhost/callback&response_type=token';
};

После успешного входа провайдер возвращает токен, который можно сохранить в localStorage и использовать в API-запросах.


Защита клиентской части

Даже при использовании токенов на клиенте необходимо учитывать:

  • XSS-атаки: нельзя хранить токены в cookie без защиты, а localStorage уязвим к скриптам на странице.
  • Обновление токена: необходимо реализовать механизм refresh-токенов для долгосрочной сессии.
  • Минимизация данных в клиенте: не хранить лишнюю личную информацию, только идентификатор и срок действия токена.

Асинхронная проверка авторизации

Часто требуется проверять валидность токена на сервере при каждой загрузке защищённого компонента. Это реализуется с помощью хука useEffect:

import { useEffect, useState } from 'preact/hooks';

function useVerifyToken(token) {
    const [valid, setValid] = useState(false);

    useEffect(() => {
        if (!token) return;

        fetch('/api/verify-token', {
            headers: { 'Authorization': `Bearer ${token}` }
        })
        .then(res => res.ok ? setValid(true) : setValid(false))
        .catch(() => setValid(false));
    }, [token]);

    return valid;
}

Такой подход позволяет динамически скрывать или показывать части интерфейса в зависимости от состояния аутентификации пользователя.


Preact обеспечивает лёгкость и гибкость при построении системы аутентификации и авторизации. Использование хуков, контекста и компонентной архитектуры позволяет строить безопасные и масштабируемые решения без потери производительности.