JWT токены в Go (Golang): создание и проверка с примерами

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

JWT токены в Go (Golang): полное руководство

JSON Web Tokens (JWT) — это открытый стандарт (RFC 7519) для создания токенов доступа, основанных на JSON. JWT широко используется для аутентификации и обмена информацией между клиентом и сервером. В языке Go (Golang) работа с JWT токенами реализуется просто и эффективно благодаря библиотеке golang-jwt/jwt.

В этой статье мы подробно разберём создание, подпись, проверку и использование JWT токенов в Go. Материал будет полезен как новичкам, так и опытным разработчикам, которые хотят внедрить безопасную аутентификацию в свои проекты на Golang.

Установка библиотеки golang-jwt

Для работы с JWT в Go используется пакет github.com/golang-jwt/jwt/v5. Установите его командой:

go get github.com/golang-jwt/jwt/v5

После установки можно импортировать пакет в ваш код:

import (
    "github.com/golang-jwt/jwt/v5"
)

Структура JWT токена

JWT токен состоит из трёх частей, разделённых точками:

  • Header (заголовок) — содержит тип токена (JWT) и алгоритм подписи (например, HS256 или RS256).
  • Payload (полезная нагрузка) — содержит данные (claims), такие как идентификатор пользователя, роль, срок действия и т.д.
  • Signature (подпись) — создаётся на основе header и payload с использованием секретного ключа или пары ключей RSA/ECDSA.

Создание JWT токена в Go

Рассмотрим пример создания JWT токена с алгоритмом HMAC-SHA256 (HS256). Для этого понадобится секретный ключ.

package main

import (
    "fmt"
    "time"
    "github.com/golang-jwt/jwt/v5"
)

func main() {
    // Секретный ключ (должен храниться в безопасном месте)
    secretKey := []byte("my_secret_key_12345")

    // Создаём claims (утверждения)
    claims := jwt.MapClaims{
        "user_id": 123,
        "role":    "admin",
        "exp":     time.Now().Add(time.Hour * 24).Unix(), // токен действует 24 часа
        "iat":     time.Now().Unix(),
    }

    // Создаём токен
    token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)

    // Подписываем токен секретным ключом
    tokenString, err := token.SignedString(secretKey)
    if err != nil {
        fmt.Println("Ошибка создания токена:", err)
        return
    }

    fmt.Println("Созданный JWT токен:")
    fmt.Println(tokenString)
}

Проверка и парсинг JWT токена

Для проверки подлинности токена используется тот же секретный ключ. Важно проверять срок действия и подпись.

package main

import (
    "fmt"
    "github.com/golang-jwt/jwt/v5"
)

func main() {
    tokenString := "ваш_токен_здесь"
    secretKey := []byte("my_secret_key_12345")

    // Парсим и проверяем токен
    token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
        // Проверяем алгоритм подписи
        if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
            return nil, fmt.Errorf("неожиданный метод подписи: %v", token.Header["alg"])
        }
        return secretKey, nil
    })

    if err != nil {
        fmt.Println("Ошибка проверки токена:", err)
        return
    }

    // Извлекаем claims
    if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
        fmt.Println("Токен валиден!")
        fmt.Printf("User ID: %v\n", claims["user_id"])
        fmt.Printf("Role: %v\n", claims["role"])
    } else {
        fmt.Println("Токен недействителен")
    }
}

Использование структурированных claims

Для удобства можно определить собственную структуру claims, реализующую интерфейс jwt.Claims:

type CustomClaims struct {
    UserID int    `json:"user_id"`
    Role   string `json:"role"`
    jwt.RegisteredClaims
}

func createCustomToken() (string, error) {
    claims := CustomClaims{
        UserID: 456,
        Role:   "user",
        RegisteredClaims: jwt.RegisteredClaims{
            ExpiresAt: jwt.NewNumericDate(time.Now().Add(24 * time.Hour)),
            IssuedAt:  jwt.NewNumericDate(time.Now()),
            Issuer:    "myapp",
        },
    }

    token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
    return token.SignedString([]byte("secret"))
}

JWT с асимметричным шифрованием (RSA)

Для повышения безопасности можно использовать пару клю

Рекомендаций