Что такое JWT (веб-токен JSON)?
JWT — это аббревиатура JSON Web Tokens. JSON Web Token (JWT) — это открытый стандарт (RFC 7519), определяющий компактный и автономный способ безопасной передачи информации между сторонами в виде объекта JSON.
Эту информацию можно проверить и доверять ей, поскольку она имеет цифровую подпись. JWT могут быть подписаны с использованием секрета (с помощью алгоритма HMAC) или пары открытого/закрытого ключа с использованием RSA или ECDSA.
Почему вы должны использовать JWT?
1. Без гражданства
JWT поддерживают принцип REST сервера без сохранения состояния. В этом случае сервер не хранит информацию о сеансе различных вызовов, сделанных от одного и того же клиента, JWT может быть отправлен в качестве заголовка авторизации в каждом вызове, что устраняет необходимость отслеживать информацию о сеансе на сервере.
2. Развязанный/децентрализованный
JWT не нужна центральная система для проверки каждого запроса. Токены можно проверять где угодно, даже в библиотеках и служебных классах.
3. Поддерживает претензии
Мы можем поместить данные JSON, называемые «требованиями», внутрь токена. Сведения о пользователе, такие как идентификатор, имя пользователя, роли и привилегии, могут быть объединены в токен, что сокращает количество сетевых вызовов, необходимых для получения этой информации с внутреннего сервера.
4. Автоматически истекает
JWT можно запрограммировать на истечение заданного времени истечения срока действия. Таким образом, нам не нужно управлять жизненным циклом токена в нашей серверной базе данных, фактически не рекомендуется хранить JWT в постоянной базе данных. Токены JWT с истекшим сроком действия будут вызывать грубые исключения, если они будут декодированы.
Когда следует использовать веб-токены JSON?
Вот несколько сценариев, в которых веб-токены JSON полезны:
- Авторизация. Это наиболее распространенный сценарий использования JWT. Как только пользователь войдет в систему, каждый последующий запрос будет включать JWT, позволяя пользователю получать доступ к маршрутам, службам и ресурсам, разрешенным с помощью этого токена.
- Обмен информацией. Веб-токены JSON — это хороший способ безопасной передачи информации между сторонами. Поскольку JWT могут быть подписаны — например, с использованием пар открытого и закрытого ключей — вы можете быть уверены, что отправители являются теми, за кого себя выдают. Кроме того, поскольку подпись вычисляется с использованием заголовка и полезной нагрузки, вы также можете убедиться, что содержимое не было подделано.
Структура веб-токена JSON
Веб-токены JSON состоят из трех частей, разделенных точками (.
):
- Заголовок
- Полезная нагрузка
- Подпись
Поэтому JWT обычно выглядит следующим образом.
xxxxx.yyyyy.zzzzz
Давайте разберем разные части.
Заголовок
Заголовок обычно состоит из двух частей: тип токена (JWT) и используемый алгоритм подписи, например HMAC SHA256 или RSA.
Например:
{
"alg": "HS256",
"typ": "JWT"
}
Затем этот JSON кодируется Base64Url для формирования первой части JWT.
Полезная нагрузка
Затем полезная нагрузка кодируется Base64Url для формирования второй части веб-токена JSON.
Полезная нагрузка — самая простая часть, это просто информация о пользователе, которого мы аутентифицируем.
sub
— аббревиатура от «тема» и обычно представляет собой идентификатор пользователя в базе данных.name
— Просто произвольные метаданные о пользователе.admin
— Еще несколько произвольных метаданных о пользователеiat
— сокращение от «выпущено в» и указывает, когда этот JWT был выпущен.
С JWT вы также можете увидеть следующую информацию в полезной нагрузке:
exp
— сокращение от «время истечения», которое указывает время, в которое истекает срок действия этого JWT.iss
— сокращение от «эмитент», которое часто используется, когда центральный сервер входа в систему выдает множество токенов JWT (также активно используется в протоколе OAuth).
Пример полезной нагрузки может быть:
{
"sub": "1234567890",
"name": "John Doe",
"admin": true
}
Подпись
Чтобы создать часть подписи, вы должны взять закодированный заголовок, закодированную полезную нагрузку, секрет, алгоритм, указанный в заголовке, и подписать это.
Например, если вы хотите использовать алгоритм HMAC SHA256, подпись будет создана следующим образом:
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
Подпись используется для проверки того, что сообщение не было изменено по пути, и, в случае токенов, подписанных с помощью закрытого ключа, она также может проверить, что отправитель JWT является тем, кем он себя называет.
Объединение всего вместе
Вывод представляет собой три строки Base64-URL, разделенные точками, которые можно легко передавать в средах HTML и HTTP, при этом они более компактны по сравнению со стандартами на основе XML, такими как SAML.
Ниже показан JWT с закодированным предыдущим заголовком и полезной нагрузкой, подписанный секретом.
Как работает JWT?
Теперь давайте напишем код:
Вы можете найти файлы исходного кода на Github, нажав нажмите здесь. Или вы также можете выполнить шаги, описанные ниже, и выходные экраны также прилагаются к этой статье.
Шаги по созданию и проверке веб-токена JSON:
Прежде всего, откройте код Visual Studio или любой другой текстовый редактор.
Шаг 1.Инициализируйте проект с помощью команды PowerShell в VSCode:
инициализация нпм
Шаг 2. Установите необходимые пакеты (express и jsonwebtoken) с помощью приведенной ниже команды:
npm установить экспресс jsonwebtoken
Шаг 3. Теперь создайте файл index.js в каталоге проекта и напишите следующий код:
const express = require('express');
const app = express();
app.get('/api', (req, res) =› {
res.json({
текст: «Мой API»
});
});
app.listen(3000, () =› {
console.log('Сервер запущен на порту 3000');
});
Шаг 4.Запустите сервер (здесь я использую nodemon.):
Введите команду в powershell:
нодмон
Чтобы проверить вывод, откройте веб-браузер (Chrome, Firefox и т. д.) и введите URL-адрес, как показано на экране вывода ниже:
локальный хост: 3000/апи
Выход:
Шаг 6. Если вы видите результат, аналогичный изображенному выше, значит, ваш API работает правильно.
Теперь пришло время работать с jwt; Для этого в первую очередь нам потребуется библиотека jwt:
Давайте импортируем это в начало файла, где мы пишем другие операторы запроса:
const jwt = require('jsonwebtoken');
Шаг 7. Создайте пользователя и назначьте ему токен
app.post(‘/api/login’, (req, res) =› {
//авторизация пользователя
постоянный пользователь = {
id: 5,
имя пользователя: «Прашант»
}
//подписываем токен
константный токен = jwt.sign(пользователь, ‘my_secret_key’);
res.json({токен});
});
Шаг 8. Откройте Postman и нажмите на запрос, как показано на рисунке ниже:
Выход:
Теперь скопируйте и сохраните этот токен где-нибудь, потому что он нужен нам для проверки и доступа к нашим защищенным данным.
Шаг 9. Проверьте и получите доступ к данным с помощью токена:
app.get('/api/protected', sureToken, (req, res) => {
jwt.verify(req.token, ‘my_secret_key’, (ошибка, данные) =› {
если (ошибка) {
res.sendStatus(403);
} еще {
res.json({
текст: «Это защищено»,
данные
});
}
});
});
функция sureToken (req, res, next) {
const BearerHeader = req.headers[‘авторизация’];
if (typeof BearerHeader != ‘undefined’) {
const Bearer = BearerHeader.split('');
const BearerToken = Bearer[1];
req.token = BearerToken;
следующий();
} еще {
res.sendStatus(403); //Запрещенный
}
}
Вывод: доступ к защищенным данным с использованием токена jwt
Теперь внесите некоторые изменения в токен и давайте посмотрим на результат:
Полный исходный код:
const Express = Требовать('Экспресс'); // включаем экспресс
const jwt = require('jsonwebtoken'); //включаем библиотеку токенов JWT
константное приложение = экспресс(); // инициализируем экспресс-сервер
app.get(‘/api’, (req, res) =› {
res.json({
текст: «Мой апи»
});
});
app.post(‘/api/login’, (req, res) =› {
//авторизация пользователя
постоянный пользователь = {
id: 5,
имя пользователя: «Прашант»
}
//подписываем токен
const token = jwt.sign({ user }, ‘my_secret_key’, { expiresIn: ‘1d’ }, (ошибка, токен) =› {
res.json({токен}); // отправка токена в ответ
});
});
// Доступ к защищенным данным с помощью токена
app.get('/api/protected', sureToken, (req, res) => {
// проверить токен с помощью секретного ключа
jwt.verify(req.token, ‘my_secret_key’, (ошибка, данные) =› {
если (ошибка) {
res.sendStatus(403); //Запрещенный
} еще {
// отправка защищенных данных в ответ, если токен проверен
res.json({
текст: «Это защищенные данные»,
данные
});
}
});
});
функция sureToken (req, res, next) {
// доступ к заголовку авторизации
const BearerHeader = req.headers[‘авторизация’];
//подтверждаем, что заголовок не должен быть неопределенного типа
if (typeof BearerHeader != ‘undefined’) {
// разделяем данные BearerHeader по пробелам и назначаем их в переменную носителя
const Bearer = BearerHeader.split('');
// извлечь токен из носителя, который находится в индексе 1 массива
const BearerToken = Bearer[1];
// сохраняем токен в req.token
req.token = BearerToken;
следующий();
} еще {
res.sendStatus(403); //Запрещенный; если BearerHeader не определен
}
}
app.listen(3000, () =› {
console.log('Сервер запущен на порту 3000');
})