Создайте безопасный API с помощью JWT
В этой статье мы собираемся создать простой RESTful API для регистрации, входа в систему и авторизации пользователей с помощью JWT, но сначала давайте взглянем на проблему, которую мы пытаемся решить здесь.
Проблема и решение
Эта проблема
Проблема здесь проста: у вас есть API, используемый клиентом (веб, мобильное приложение, интерфейс командной строки и т. Д.), И вы хотите защитить его и разрешить доступ к нему только зарегистрированным пользователям.
Решение
Решением будет использование веб-токенов JSON (для краткости JWT) для входа в систему и авторизации пользователей, как показано на простом изображении ниже.
- Клиент войдет в систему, отправив учетные данные на сервер API.
- Сервер API проверит учетные данные пользователя, подпишет JWT и вернет его в ответе HTTP.
- Клиент будет использовать полученный JWT для доступа к ресурсам API.
- Сервер API проверит JWT и разрешит пользователю доступ к ресурсу.
Что такое JWT?
Веб-токен JWT или JSON - это строка с цифровой подписью, используемая для безопасной передачи информации между сторонами. Это стандарт RFC7519.
JWT состоит из трех частей:
header.payload.signature
Ниже представлен образец JWT.
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
Заголовок
Заголовок представляет собой строку в кодировке Base64 и содержит тип токена (в данном случае JWT
) и алгоритм подписи (в данном случае HMAC SHA256
или для краткости HS256
).
{
"alg": "HS256",
"typ": "JWT"
}
Полезная нагрузка
Полезные данные - это строка в кодировке Base64, содержащая утверждения. Утверждения - это набор данных, связанных с пользователем и самим токеном. Примеры претензий: exp
(срок действия), iat
(выдан в), name
(имя пользователя) и sub
(тема).
{ "sub": "1234567890", "name": "John Doe", "iat": 1516239022 }
Вы можете узнать больше о претензиях здесь.
Подпись
Подпись - это подписанная строка. Для алгоритмов подписи HMAC мы используем заголовок в кодировке Base64, полезные данные в кодировке Base64 и секрет подписи для их создания.
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
JWT в Голанге
Теперь, когда у нас есть лучшее представление о JWT, давайте создадим наш небольшой API аутентификации на Golang.
Запустить модуль Go
Создайте новый каталог в вашем GOPATH
, назовите его authapp
, а затем запустите модуль Go.
go mod init
База данных
Чтобы упростить изучение, я собираюсь использовать базу данных SQLite.
Для работы с базами данных SQL в Go я настоятельно рекомендую использовать ORM, например GORM, поэтому давайте установим его вместе с драйвером SQLite. .
go get -u gorm.io/gorm go get -u gorm.io/driver/sqlite
Теперь создайте новую папку с именем database и используйте этот код для запуска глобального объекта базы данных.
А теперь давайте проверим это.
Тест пройден, и наша база данных готова. Перейдем к пользовательской модели.
Модель пользователя
Модель пользователя в нашем случае проста: у нее есть имя, адрес электронной почты и пароль.
Пароль пользователя должен быть хеширован в базе данных, и для этого мы используем замечательную библиотеку bcrypt.
go get "golang.org/x/crypto/bcrypt"
Вот полная модель User с функциями для создания записи в базе данных, хэша и проверки пароля.
Теперь давайте проверим всю приведенную выше логику.
Все идет нормально. Теперь перейдем к подписанию JWT.
Подписание и проверка JWT
Чтобы подписать и проверить токены JWT в Golang, мы собираемся использовать пакет jwt-go.
go get github.com/dgrijalva/jwt-go
Теперь давайте создадим специальный пакет, в котором мы сможем подписывать и проверять токены.
Я назвал его просто auth
, и он имеет следующие структуры и функции:
- структура
JwtWrapper
для обертывания ключа подписи, эмитента и срока действия в часах - структура
JwtClaim
для добавления настраиваемого электронного запроса к нашему токену GenerateToken
функция для генерации с использованием HS256 токена, срок действия которого истекает через 24 часаValidateToken
функция, которая проверяет токен и возвращает утверждения
Ниже приведен полный код.
Время тестирования:
Большой! Теперь, когда у нас есть наша пользовательская модель и логика подписи / проверки JWT, пришло время создать фактические API.
API
В этом разделе мы собираемся создать три конечные точки RESTful API.
[POST] /api/public/signu
p = ›создает пользователя[POST] /api/public/login
= ›выполняет вход пользователя в систему и возвращает JWT[GET] /api/private/profile
= ›авторизует пользователя и возвращает запрошенные данные
Но прежде чем мы начнем, нам нужно установить отличный веб-фреймворк gin-gonic .
go get -u github.com/gin-gonic/gin
Теперь давайте настроим наш главный файл, чтобы создать базу данных и маршрутизатор джина и запустить сервер.
Давай проверим.
Наш HTTP-роутер готов. Теперь давайте создадим контроллер регистрации.
Регистрация
Регистрация - это общедоступный API; он не должен требовать аутентификации.
Чтобы создать контроллер джина, создайте пакет с именем controllers
и файл с именем public.go
.
Запрос POST. Мы должны получить полезную нагрузку и проверить ее, вставить пользователя в базу данных и вернуть вставленного пользователя.
Логин
Здесь логин простой. Зарегистрированный пользователь просто предоставит адрес электронной почты и имя пользователя, и мы подпишем для них токен.
Давайте проверим как регистрацию, так и вход в систему.
Здесь мы проводим модульное тестирование, но давайте создадим наши маршруты и протестируем реальную вещь в Postman.
Добавьте следующий код в файл main.go
.
Теперь запустим сервер.
go run main.go
Давайте проверим это в Postman.
Очень хороший! Давайте проверим наш токен в JWT.
Потрясающие! Теперь пользователь может создать учетную запись, войти в систему и получить токен.
Давайте создадим защищенный маршрут, доступ к которому будут иметь только прошедшие аутентификацию пользователи.
Защищенный ресурс
Ресурс здесь будет профилем пользователя. Здесь все просто: он вернет данные пользователя клиенту.
Что-то здесь странное. Мы не проводили проверки токенов! Обратите внимание, как мы получили письмо из контекста джин.
Авторизация пользователей и проверка токенов должны происходить в промежуточном программном обеспечении, и причина проста: не повторяйтесь.
Но прежде чем переходить к промежуточному программному обеспечению авторизации, давайте протестируем этот контроллер профиля.
Очень хороший. Теперь перейдем к промежуточному программному обеспечению.
Промежуточное ПО авторизации
Промежуточное ПО находится между клиентом и ресурсом, поэтому еще до того, как мы коснемся базы данных, будет вызвано промежуточное ПО для проверки токена и авторизации пользователя. Логика авторизации предельно проста:
- Проверьте, присутствует ли JWT в заголовке авторизации.
- Проверьте формат токена.
- Подтвердите токен.
- Перейдите к контроллеру.
Создайте пакет с именем middlewares
и добавьте следующий код.
Время тестирования:
Отлично! Наше промежуточное ПО для авторизации прекрасно работает. Теперь давайте добавим правильный маршрут в наш основной маршрутизатор и сами посмотрим на результаты в Postman.
Похоже, это работает!
Резюме
Вот и все, ребята! Надеюсь, вам понравилась эта статья.
Я загрузил код на GitHub
Дополнительная литература: Обновить токены: когда их использовать и как они взаимодействуют с JWT