Как JSON Web Token (JWT) защищает ваш API
Вы, наверное, слышали, что JSON Web Token (JWT) — это современная современная технология для защиты API.
Как и в большинстве тем, связанных с безопасностью, важно понимать, как это работает (по крайней мере, отчасти), если вы планируете его использовать. Проблема в том, что большинство объяснений JWT являются техническими и вызывают головную боль.
Давайте посмотрим, смогу ли я объяснить, как JWT может защитить ваш API, не коснувшись глаз!
API-аутентификация
К некоторым ресурсам API требуется ограниченный доступ. Например, мы не хотим, чтобы один пользователь мог изменить пароль другого пользователя.
Вот почему мы защищаем определенные ресурсы, заставляя пользователей предоставлять свой идентификатор и пароль, прежде чем разрешить доступ — другими словами, мы аутентифицируем их.
Сложность защиты HTTP API заключается в том, что запросы лица без гражданства — API не может узнать, были ли какие-либо два запроса от одного и того же пользователя или нет.
Так почему бы нам не требовать от пользователей предоставления своего идентификатора и пароля при каждом вызове API? Только потому, что это было бы ужасным пользовательским опытом.
Веб-токен JSON
Что нам нужно, так это способ, позволяющий пользователю предоставить свои учетные данные только один раз, но затем сервер идентифицирует его другим способом в последующих запросах.
Для этого было разработано несколько систем, и в настоящее время самым современным стандартом является JSON Web Token.
Есть отличная статья по теме что делает хорошую аналогию о том, как работают веб-токены JSON:
Вместо API представьте, что вы регистрируетесь в отеле. «Жетон» — это полученная вами пластиковая карточка безопасности отеля, которая позволяет вам получить доступ к вашему номеру и объектам отеля, но не к чьему-либо другому номеру.
Когда вы выезжаете из отеля, вы возвращаете карту. Это аналогично выходу из системы.
Структура токена
Обычно веб-токен JSON отправляется через заголовок HTTP-запроса. Вот как он выглядит:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.dozjgNryP4J3jVmNHl0w5N_XgL0n3I9PlFUP0THsR8U
На самом деле токен — это часть после «Авторизация: носитель», которая является просто информацией заголовка HTTP.
Прежде чем вы решите, что это непонятная тарабарщина, есть несколько вещей, которые вы можете легко заметить.
Во-первых, токен состоит из трех разных строк, разделенных точкой. Эти три строки кодировка base 64 и соответствуют заголовок, полезная нагрузкаи подпись.
// Header
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
// Payload
eyJzdWIiOiIxMjM0NTY3ODkwIn0
// Signature
dozjgNryP4J3jVmNHl0w5N_XgL0n3I9PlFUP0THsR8U
Примечание: base 64 — это способ преобразования строк, чтобы гарантировать, что они не испортятся во время передачи по сети. Это не шифрование, и любой может легко расшифровать это чтобы увидеть исходные данные.
Мы можем расшифровать эти строки, чтобы лучше понять структуру JWT.
Ниже приведен декодированный заголовок токена. Заголовок представляет собой метаинформацию о токене. Это не говорит нам многого, чтобы помочь нам построить наше базовое понимание, поэтому мы не будем вдаваться в подробности.
{
"alg": "HS256",
"typ": "JWT"
}
Полезная нагрузка
Полезная нагрузка представляет гораздо больший интерес. Полезная нагрузка может включать любые данные, которые вам нравятся, но вы можете просто включить идентификатор пользователя, если целью вашего токена является аутентификация доступа к API.
{
"userId": "1234567890"
}
Важно отметить, что полезная нагрузка не защищена. Любой может расшифровать токен и точно увидеть, что находится в полезной нагрузке. По этой причине мы обычно включаем идентификатор, а не конфиденциальную идентифицирующую информацию, такую как адрес электронной почты пользователя.
Несмотря на то, что эта полезная нагрузка — это все, что необходимо для идентификации пользователя в API, она не предоставляет средств аутентификации. Кто-то может легко найти ваш идентификатор пользователя и подделать токен, если это все, что было включено.
Итак, это подводит нас к подписи, которая является ключевой частью аутентификации токена.
Алгоритмы хеширования
Прежде чем мы объясним, как работает подпись, нам нужно определить, что такое алгоритм хеширования.
Начнем с того, что это функция для преобразования строки в новую строку, которая называется хэш. Например, предположим, что мы хотели хешировать строку «Hello, world». Вот результат, который мы получили бы, используя алгоритм хеширования SHA256:
4ae7c3b6ac0beff671efa8cf57386151c06e58ca53a78d83f36107316cec125f
Наиболее важным свойством хэша является то, что вы не можете использовать алгоритм хеширования, чтобы идентифицировать исходную строку, глядя на хэш.
Существует множество различных типов алгоритмов хеширования, но SHA256 обычно используется с JWT.
Другими словами, мы не мочь возьмите приведенный выше хеш и сразу выясните, что исходная строка была «Hello, world». Хэш достаточно сложен, чтобы угадать исходную строку было бы невозможно.
<контент-объявление/>
JWT-подпись
Итак, возвращаясь к структуре JWT, давайте теперь посмотрим на третью часть токена, подпись. Это действительно нужно рассчитать:
HMACSHA256(
base64UrlEncode(header) + "." + base64UrlEncode(payload),
"secret string"
);
Вот объяснение того, что здесь происходит:
Во-первых, HMACSHA256
является именем хеш-функции и принимает два аргумента; строка для хеширования и «секрет» (определено ниже).
Во-вторых, строка, которую мы хешируем, представляет собой заголовок в кодировке base 64, а также полезную нагрузку в кодировке base 64.
В-третьих, секрет — это произвольный фрагмент данных, который только сервер знает.
Вопрос. Зачем включать заголовок и полезные данные в хэш подписи?
Это гарантирует, что подпись уникальна для этого конкретного токена.
В. В чем секрет?
Чтобы ответить на этот вопрос, давайте подумаем, как бы вы подделали токен.
Ранее мы говорили, что вы не можете определить ввод хэша, глядя на вывод. Однако, поскольку мы знаем, что подпись включает в себя заголовок и полезную нагрузку, поскольку они являются общедоступной информацией, если вы знаете алгоритм хэширования (подсказка: он обычно указывается в заголовке), вы можете сгенерировать такой же хеш.
Но секрет, который знает только сервер, нет публичная информация. Включение его в хэш предотвращает создание собственного хэша для подделки токена. А поскольку хэш скрывает информацию, использованную для его создания, никто также не может узнать секрет из хэша.
Процесс добавления приватных данных в хэш называется соление и делает взлом токена практически невозможным.
Процесс аутентификации
Итак, теперь у вас есть хорошее представление о том, как создается токен. Как вы используете его для аутентификации вашего API?
Авторизоваться
Токен генерируется, когда пользователь входит в систему, и сохраняется в базе данных с моделью пользователя.
логинконтроллер.js
if (passwordCorrect) {
user.token = generateToken(user.id);
user.save();
}
Затем токен прикрепляется как authorization
заголовок в ответ на запрос на вход.
логинконтроллер.js
if (passwordCorrect) {
user.token = generateToken(user.id);
user.save();
res.headers("authorization", `Bearer ${token}`).send();
}
Аутентификация запросов
Теперь, когда у клиента есть токен, он может прикрепить его к любым будущим запросам для аутентификации пользователя.
Когда сервер получает запрос с прикрепленным токеном авторизации, происходит следующее:
- Он декодирует токен и извлекает идентификатор из полезной нагрузки.
- Он ищет пользователя в базе данных с этим идентификатором.
- Он сравнивает токен запроса с тем, который хранится в модели пользователя. Если они совпадают, пользователь аутентифицируется.
authMiddleware.js
const token = req.header.token;
const payload = decodeToken(token);
const user = User.findById(payload.id);
if (user.token = token) {
} else {
}
Выход
Если пользователь выходит из системы, просто удалите токен, прикрепленный к модели пользователя, и теперь токен больше не будет работать. Пользователю потребуется снова войти в систему, чтобы сгенерировать новый токен.
logoutController.js
user.token = null;
user.save();
Заворачивать
Итак, это очень простое объяснение того, как вы можете защитить API с помощью веб-токенов JSON. Надеюсь, у тебя не сильно болит голова.
Тем не менее, в этой теме гораздо больше, поэтому вот некоторые дополнительные материалы для чтения:
Станьте старшим разработчиком Vue в 2020 году.
Изучите и освойте знания профессионалов о создании, тестировании и развертывании полнофункциональных приложений Vue в нашем последнем курсе.