Мы узнаем, как защитить маршрут с помощью JWT-аутентификации в react-router-dom v6. Маршруты будут доступны только в том случае, если пользователи сохранили токен в файлах cookie (или в локальном хранилище).


Используемые технологии

  • Реагировать ^ 18.2.0;
  • JWT;
  • Аксиос ^0,27,2;
  • реакция-маршрутизатор-дом ^ 6.3.0;
  • реактивное печенье ^ 4.1.1;


Начиная

Давайте создадим React-приложение

create-react-app protect-route-with-jwt
Войти в полноэкранный режим

Выйти из полноэкранного режима

Эта команда создаст структуру проекта реакции с некоторыми необходимыми файлами. Удалите некоторые файлы и создайте несколько папок, которые будут использоваться в проекте. Окончательная структура будет такой:
Описание изображения

Теперь мы собираемся установить некоторые зависимости проекта, открыть терминал внутри папки проекта и выполнить следующие команды:

yarn init
yarn add axios
yarn add react-router-dom
yarn add react-cookie
Войти в полноэкранный режим

Выйти из полноэкранного режима


Определение API

Создайте файл в src > services > api.js где мы определим baseURL для выполнения запросов в нашем приложении:

import axios from 'axios';

const api = axios.create({
    baseURL: "http://localhost:8000" //your api URL
});

export default api;
Войти в полноэкранный режим

Выйти из полноэкранного режима

исходный код > услуги > api.js

Мы определяем нашу переменную API из библиотеки axios и экспортируем ее.


Создание хуков

Перейдите к src > hooks создание двух папок, auth иprotect Routes. Внутри них и hooks папке создайте файл index.js.
Описание изображения


авторизация

import { createContext, useContext, useMemo } from 'react';
import { useCookies } from 'react-cookie';
import { useNavigate } from 'react-router-dom';
import api from '../../services/api';

const UserContext = createContext();

export const UserProvider = ({ children }) => {
    const navigate = useNavigate();
    const [cookies, setCookies, removeCookie] = useCookies(['session']);

    const login = async ({ email, password }) => {
        const res = await api.post('/auth', {
            email: email,
            password: password
        });

        setCookies('token', res.data.token); // your token
        setCookies('name', res.data.name); // optional data

        navigate('/home');
    };

    const logout = () => {
        ['token', 'name'].forEach(obj => removeCookie(obj)); // remove data save in cookies
        navigate('/login');
    };

    const value = useMemo(
        () => ({
            cookies,
            login,
            logout
        }),
        [cookies]
    );

    return (
        <UserContext.Provider value={value}>
            {children}
        </UserContext.Provider>
    )
};

export const useAuth = () => {
    return useContext(UserContext)
};
Войти в полноэкранный режим

Выйти из полноэкранного режима

src > ловушки > авторизация > index.js

По сути, здесь мы создаем пользовательский контекст, который имеет функции входа и выхода, и экспортируем его, чтобы его можно было использовать через дерево компонентов без необходимости вручную передавать реквизиты на каждом уровне. Если вы не понимаете см. контекстAPI документация.


ProtectRoutes

import { Outlet, Navigate } from 'react-router-dom';
import { useAuth } from '../auth';

export const ProtectRoutes = () => {
    const { cookies } = useAuth();

    return cookies.token ? <Outlet/> : <Navigate to='/login' exact />
};
Войти в полноэкранный режим

Выйти из полноэкранного режима

src > ловушки > ProtectRoutes > index.js

Здесь мы создаем защиту маршрута, используя наш useAuth, который мы определили ранее, если он существует. жетон в файлах cookie следите за приложением, иначе перенаправляйте на страницу входа.


крючки

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

import { UserProvider } from './auth';

const AppProvider = ({ children }) => (
    <>
        <UserProvider>{ children }</UserProvider>
    </>
);

export default AppProvider;
Войти в полноэкранный режим

Выйти из полноэкранного режима

src > хуки > index.js

Теперь все, что мы поместим внутрь AppProvider, сможет получить доступ к хуку useAuth.


Создание страниц

Для этого примера создайте две страницы: домашнюю и страницу входа. Они будут находиться в src > pages:
Описание изображения
Примеры страниц будут такими:

import React from 'react';

export default function Home() {
    return <div>Home Page</div>
}

Войти в полноэкранный режим

Выйти из полноэкранного режима

src > страницы > Главная > index.js

import React from 'react';

export default function Login() {
    return <div>Login Page</div>
}

Войти в полноэкранный режим

Выйти из полноэкранного режима

src> страницы> Войти> index.js


Создание маршрутов

Перейдите к index.js папки src и добавьте следующий код:

import React from 'react';
import ReactDOM from 'react-dom/client';
import { BrowserRouter } from 'react-router-dom';
import AppProvider from './hooks';
import App from './App';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <BrowserRouter>
      <AppProvider>
        <App />
      </AppProvider>
    </BrowserRouter>
  </React.StrictMode>
);
Войти в полноэкранный режим

Выйти из полноэкранного режима

исходный код > index.js

Определим маршруты некоторых приложений и, наконец, защитим их. Перейдите к App.js и добавьте следующий код:

import React from 'react';
import { Route, Routes, Navigate } from 'react-router-dom';
import { ProtectRoutes } from './hooks/protectRoutes';
import Home from './pages/Home';
import Login from './pages/Login';

export default function App() {
  return (
    <Routes>
      <Route path='/' element={ <Navigate to='home' exact /> } />
      <Route path='/login' element={ <Login /> } />

      <Route element={ <ProtectRoutes /> }>
        <Route path='/home' element={ <Home /> } />
      </Route>
    </Routes>
  )
}
Войти в полноэкранный режим

Выйти из полноэкранного режима

исходный код > App.js

Здесь мы определяем маршруты внутри Routes составная часть. Чтобы добавить наш защищенный маршрут вокруг маршрутов, которые мы хотим защитить, достаточно открыть <Route> тег с нашим ProtectRoutes как элемент. Внутри тега мы добавим маршруты, в этом случае мы защищаем домашний маршрут, то есть пользователь сможет получить к нему доступ только в том случае, если у него есть токен в файлах cookie, что мы и определили в защите от маршрут ранее.

Вот и все, теперь все маршруты, которые вам нужно защитить с помощью аутентификации пользователя, должны быть помещены в Route, которые имеют <ProtectRoutes> элемент.

Вы можете получить доступ к этому проекту в моем github: