Что такое 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');

})