JavaRush /Курсы /Модуль 3: React /Создание AuthGuard для защиты маршрутов с использованием ...

Создание AuthGuard для защиты маршрутов с использованием JWT

Модуль 3: React
16 уровень , 5 лекция
Открыта

Создаём AuthGuard для защиты маршрутов

1. Установка и настройка react-router-dom

Если вы ещё не установили библиотеку для маршрутизации, сделайте это:

npm install react-router-dom

Не забудьте, что при работе с TypeScript, вам понадобится типизация для роутера:

npm install @types/react-router-dom --save-dev

Теперь у нас есть все инструменты, чтобы начать создание.

2. Структура приложения

Давайте обновим нашу структуру проекта. Мы будем использовать следующие основные компоненты:

  • App.tsx: основной файл с маршрутизацией.
  • ProtectedRoute.tsx: наш AuthGuard.
  • AuthService.ts: сервис для работы с JWT (генерация, валидация и т.д.).
  • Компоненты страниц LoginPage, Dashboard, Profile.

Ваш каталог может выглядеть так:

src/
├── components/
│   ├── ProtectedRoute.tsx
│   ├── LoginPage.tsx
│   ├── Dashboard.tsx
│   └── Profile.tsx
└── services/
    └── AuthService.ts

3. Реализация AuthService

Начнем с сервиса авторизации. Он помогает управлять токенами: извлекать их из localStorage, проверять их валидность и, при необходимости, удалять.

src/services/AuthService.ts:

export default class AuthService {
  private static TOKEN_KEY = 'app_token';

  // Сохраняем токен в localStorage
  static setToken(token: string) {
    localStorage.setItem(this.TOKEN_KEY, token);
  }

  // Получаем токен из localStorage
  static getToken(): string | null {
    return localStorage.getItem(this.TOKEN_KEY);
  }

  // Удаляем токен (выход пользователя)
  static clearToken() {
    localStorage.removeItem(this.TOKEN_KEY);
  }

  // Проверяем валидность токена
  static isTokenValid(): boolean {
    const token = this.getToken();
    if (!token) return false;

    try {
      const payload = JSON.parse(atob(token.split('.')[1])); // Декодируем payload JWT
      const currentTime = Math.floor(Date.now() / 1000);
      return payload.exp > currentTime; // Сравниваем срок действия токена
    } catch (error) {
      console.error('Invalid token:', error);
      return false;
    }
  }
}

Этот сервис выполняет простую, но важную функцию — он проверяет срок действия токена и управляет его состоянием в localStorage.

4. Реализация ProtectedRoute

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

src/components/ProtectedRoute.tsx:

import React from 'react';
import { Navigate } from 'react-router-dom';
import AuthService from '../services/AuthService';

interface ProtectedRouteProps {
  children: React.ReactElement; // Дочерний компонент (например, Dashboard)
}

const ProtectedRoute: React.FC<ProtectedRouteProps> = ({ children }) => {
  const isAuthenticated = AuthService.isTokenValid();

  if (!isAuthenticated) {
    // Перенаправляем пользователя на страницу входа
    return <Navigate to="/login" replace />;
  }

  // Если пользователь аутентифицирован, отображаем дочерний компонент
  return children;
};

export default ProtectedRoute;

Обратите внимание на использование компонента Navigate из react-router-dom для перенаправления.

5. Настройка маршрутов в App.tsx

Теперь мы можем использовать наш AuthGuard для защиты маршрутов. Добавим ProtectedRoute в нашу маршрутизацию.

src/App.tsx:

import React from 'react';
import { BrowserRouter as Router, Route, Routes } from 'react-router-dom';

import LoginPage from './components/LoginPage';
import Dashboard from './components/Dashboard';
import Profile from './components/Profile';
import ProtectedRoute from './components/ProtectedRoute';

const App: React.FC = () => {
  return (
    <Router>
      <Routes>
        <Route path="/login" element={<LoginPage />} />
        {/* Защищённый маршрут для Dashboard */}
        <Route
          path="/dashboard"
          element={
            <ProtectedRoute>
              <Dashboard />
            </ProtectedRoute>
          }
        />
        {/* Защищённый маршрут для Profile */}
        <Route
          path="/profile"
          element={
            <ProtectedRoute>
              <Profile />
            </ProtectedRoute>
          }
        />
        {/* Страница по умолчанию */}
        <Route path="*" element={<Navigate to="/login" replace />} />
      </Routes>
    </Router>
  );
};

export default App;

Теперь любой маршрут, обёрнутый в ProtectedRoute, автоматически проверяется на валидность JWT.

6. Типичные проблемы и их решения

Проблема: JWT истёк, пользователь остаётся на странице.

Решение: добавьте проверку токена в компоненте верхнего уровня, например, в App.tsx. Если токен истёк, вызывайте AuthService.clearToken() и перенаправляйте на /login.

Проблема: пользователь видит мигание защищённого маршрута перед редиректом.

Решение: используйте состояние загрузки isLoading в ProtectedRoute, чтобы дождаться проверки токена перед рендерингом.

2
Задача
Модуль 3: React, 16 уровень, 5 лекция
Недоступна
Проверка токена на валидность
Проверка токена на валидность
Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ