Go становится очень популярным для разработки бэкенда, а JWT — один из самых популярных способов аутентификации при запросах API. В этой статье мы рассмотрим основы JWT и способы реализации безопасной стратегии аутентификации в Go! Поехали
Что такое JWT?
JSON Web Token (JWT, произносится /dʒɒt/, то же, что и слово «jot»[1]) — это предлагаемый интернет-стандарт для создания данных с необязательной подписью и/или необязательным шифрованием, полезная нагрузка которых содержит JSON, утверждающий некоторое количество утверждений. Токены подписываются либо с использованием закрытого секрета, либо с использованием открытого/закрытого ключа.
JWT по сути являются закодированными объектами JSON, которые были подписаны сервером, что доказывает их подлинность.
Например, когда пользователь входит на веб-сайт, защищенный с помощью JWT, процесс должен выглядеть следующим образом:
-
Пользователь отправляет на сервер имя пользователя и пароль.
-
Сервер проверяет правильность имени пользователя и пароля.
-
Сервер создает объект JSON, который выглядит следующим образом:
{«username»: «adam»} -
Сервер кодирует и подписывает объект JSON, создавая JWT:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKKF2QT4fwpMeJf36POk6yJV_adQssw5c -
Веб-клиент пользователя сохраняет JWT для последующего использования
-
Когда пользователь делает запрос к защищенной конечной точке, JWT передается в HTTP-заголовке.
-
Сервер проверяет подпись на JWT, чтобы убедиться, что JWT был первоначально создан тем же сервером.
-
Сервер считывает утверждения и дает разрешение на выполнение запроса от имени «adam».
Создание JWT
Прежде чем мы создадим JWT, мы воспользуемся библиотекой для работы с JSON Web Token в go с помощью golang-jwt. Убедитесь, что код клонирован в вашей локальной сети, выполнив следующую команду :
go get github.com/golang-jwt/jwt/v4
Это означает, что мы предполагаем, что сервер, который генерирует JWT, будет также единственным сервером, который их проверяет.
Сначала определим структуру, которая будет использоваться для представления утверждений или идентификации данных пользователей:
Структура jwt.StandardClaims содержит такие полезные поля, как срок действия, имя эмитента, субъект и т.д. Теперь мы создадим несколько фактических утверждений для пользователя, который только что вошел в систему:
После этого создадим неподписанный токен из утверждений:
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
Подпишите токен с помощью надежного закрытого ключа. Убедитесь, что вы используете настоящий закрытый ключ, желательно длиной не менее 256 бит:
signedToken, err := token.SignedString([]byte(“secureSecretText”))
Теперь подписанный токен может быть отправлен обратно клиенту.
Проверка подлинности JWT
Когда клиент запрашивает защищенную конечную точку, мы можем использовать следующие шаги для проверки JWT.
Примечание: Использование HTTP-заголовка Authorization является идиоматическим:
Authorization: Bearer {jwt}
После получения JWT используйте тот же закрытый ключ для подтверждения утверждений и проверки подписи.
token, err := jwt.ParseWithClaims(
jwtFromHeader,
&customClaims{},
func(token *jwt.Token) (interface{}, error) {
return []byte("secureSecretText"), nil
},
)
Переменная err не будет равна нулю, если утверждения были подделаны. Разберите следующие утверждения из токена:
claims, ok := token.Claims.(*customClaims)
if !ok {
return errors.New("Couldn't parse claims")
}
Проверьте, не истек ли срок действия токена:
if claims.ExpiresAt < time.Now().UTC().Unix() {
return errors.New("JWT is expired")
}
Теперь вы знаете имя пользователя, прошедшего аутентификацию!
username := claims.Username
Для полного примера посмотрите этот пример.
Спасибо за прочтение!
Доступен для нового проекта! Давайте поговорим bangadam.dev@gmail.com