В этом блоге мы рассмотрим, как мы можем аутентифицировать пользователя с помощью JSON Web Token, также известного как JWT. JWT — один из лучших стандартов для реализации системы аутентификации в вашем приложении стека MERN.

JSON Web Token (JWT) — это открытый стандарт (RFC 7519), определяющий компактный и автономный способ безопасной передачи информации между сторонами в виде объекта JSON. Эту информацию можно проверить и ей можно доверять, поскольку она имеет цифровую подпись. JWT можно подписать с помощью секрета (с помощью алгоритма HMAC) или пары открытого/закрытого ключей с использованием RSA или ECDSA.

Когда нам следует использовать JWT?

  • Авторизация. Это наиболее распространенный сценарий использования JWT. После входа пользователя в систему каждый последующий запрос будет включать JWT, что позволяет пользователю получать доступ к маршрутам, службам и ресурсам, разрешенным с помощью этого токена. Единый вход — это функция, которая в настоящее время широко использует JWT из-за ее небольших накладных расходов и возможности легкого использования в разных доменах.
  • Обмен информацией. Веб-токены JSON – это хороший способ безопасной передачи информации между сторонами.

Какова структура веб-токена JSON?

В своей компактной форме веб-токены JSON состоят из трех частей, разделенных точками (.), а именно:

  • Заголовок
  • Полезная нагрузка
  • Подпись

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

Ххххх.yyyyy.zzzzz

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

Серверная реализация:

Итак, ниже я поделился некоторыми фрагментами кода с некоторыми пояснениями. Ниже этих фрагментов кода мы проверим, не существует ли зарегистрированный пользователь в базе данных, затем он зашифрует пароль для хранения в базе данных и создаст пользователя. После создания пользователя он создаст токен JWT, используя идентификатор созданного пользователя и имя пользователя. Вы также можете использовать любой тип вводимых данных, например адрес электронной почты или номер телефона. Но я предлагаю также каждый раз включать идентификатор пользователя, чтобы сохранить уникальность токена.

  1. Создание JWT
jwt.sign({
        id: response.user_id,
        name: response.user_name
    },
    config.get("jwtSecret"), {
        expiresIn: 86400
    },
    (err, token) => {
        if (err) throw err;
        res.status(200).json({
            expiresIn: 1 d,
            data: response,
            token: token,
        });
    }
);

Итак, как я упоминал ранее, токен JWT принимает 3 параметра. Первый параметр — это метод «sign», который принимает информацию, которую необходимо поместить в полезную нагрузку, которая преобразуется в токен JWT.

Второй параметр — это секретный ключ, используемый для создания дайджеста.

Третий параметр — это представление опции. Итак, в этом примере я установил срок действия токена в секундах.

2. Проверьте JWT с помощью промежуточного программного обеспечения:

const jwt = require("jsonwebtoken");
const config = require("config");

module.exports = function(req, res, next) {
    const token = req.header("Authorization");
    if (!token) {
        return res.status(401).json({
            msg: "Authorization denied",
        });
    }

    try {
        const decoded = jwt.verify(token, config.get("jwtSecret"));
        req.user = decoded;
        next();
        j
    } catch (err) {
        res.status(401).json({
            msg: "invalid token",
        });
    }
};

В приведенном выше примере я реализовал промежуточное программное обеспечение Express.js, которое проверяет наличие токена и проверяет переданный нами токен.

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

В результате лучших практик проверки токена мы отправляем коды состояния 401 (неавторизованный), если токен недействителен или срок его действия истек, и 400 (неверный запрос), если токен отсутствует в заголовках.

Реализация на стороне клиента:

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

  1. Создайте реагирующее приложение:
npx create-react-app blogapp-fe
cd blogapp-fe
npm start

Итак, если вы новичок в React.js, приведенные выше команды создадут приложение React с именем blogapp-fe с небольшим стандартным кодом и запустят сервер.

2. Создайте страницы аутентификации:

Как только ваш сервер заработает, создайте базовые страницы аутентификации для регистрации и входа. И при нажатии кнопки мы вызовем соответствующие API.

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

import React, {
    useState
} from 'react';
const SignupComponent = () => {
    const [name, setName] = useState('');
    const [email, setEmail] = useState('');
    const [password, setPassword] = useState('');
    const handleSubmit = async (e) => {
        e.preventDefault();
        // Create a user object with the form data
        const user = {
            name,
            email,
            password
        };
        try {
            // Make a POST request to the API endpoint
            const response = await fetch('http://localhost:8080/signup', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                },
                body: JSON.stringify(user)
            });
            // Check if the request was successful if (response.ok)
            {
                const data = await response.json();
                console.log('Signup successful:', data);
                // Reset form fields
                setName('');
                setEmail('');
                setPassword('');
            } else {
                console.log('Signup failed:', response.status);
            }
        } catch (error) {
            console.log('An error occurred:', error);
        }
    };
    return ( <
        form onSubmit = {
            handleSubmit
        } >
        <
        label >
        Name: < input type = "text"
        value = {
            name
        }
        onChange = {
            (e) => setName(e.target.value)
        }
        /> <
        /label> <
        br / >
        <
        label >
        Email: < input type = "email"
        value = {
            email
        }
        onChange = {
            (e) => setEmail(e.target.value)
        }
        /> <
        /label> <
        br / >
        <
        label >
        Password: < input type = "password"
        value = {
            password
        }
        onChange = {
            (e) => setPassword(e.target.value)
        }
        /> <
        /label> <
        br / >
        <
        button type = "submit" > Sign Up < /button> <
        /form>
    );
};
export default SignupComponent;

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

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

Теперь в приведенном ниже фрагменте я сделал фиктивный вызов API get, который аутентифицируется с использованием токена доступа, который передается внутри заголовков запроса в качестве авторизации. И если токен действителен, он даст ответ с кодом состояния 200.

И если он недействителен или не пройден, наше промежуточное программное обеспечение аутентификации выдаст ошибку 401 с сообщением об ошибке недействительного токена.

Пример на стороне сервера:

app.get('/data', auth, (req, res) => {
    const data = {
        message: 'Data fetched successfully'
    };
    res.json(data);
});

Здесь auth — это наше промежуточное программное обеспечение, которое необходимо импортировать.

Пример на стороне клиента:

const fetchData = async () => {
    try {
        const response = await fetch('http://localhost:8080/data', {
            method: 'GET',
            headers: {
                'Content-Type': 'application/json',
                'Authorization': 'Bearer YOUR_AUTH_TOKEN' // Replace YOUR_AUTH_TOKEN with token
            }
        });
        if (response.ok) {
            const data = await response.json();
            console.log('Data fetched successfully:', data);
        } else {
            console.log('Failed to fetch data:', response.status);
        }
    } catch (error) {
        console.log('An error occurred:', error);
    }
};

Заключение:

Итак, используя все эти примеры, вы можете легко реализовать приложение MERN со всей необходимой аутентификацией. Веб-токен JSON хорошо поддерживается и прост в использовании. На их официальном сайте вы можете найти библиотеки и инструменты для использования практически на любом языке — от Nodejs до Java и от .Net до Python.