Создание и анализ JWT в Go
В этой статье мы покажем вам, как создавать и анализировать токены JWT, извлекая из них информацию на прекрасном языке Go, используя пакет go-jwt.
Данная статья предполагает следующее:
- Вы умеете программировать на Go .
- Вы знаете, что такое JWT и как они работают.
Добавление пакета go-jwt
Мы будем использовать пакет go-jwt для создания и анализа токенов JWT.
go get -u github.com/golang-jwt/jwt/v4
На момент написания этой статьи последняя версия этого пакета — v4
.
Создание токена JWT
При создании токена JWT нам нужен секретный ключ, поэтому начните с определения нового ключа.
package main const key = "my secure jwt key" func main() { } main.go
Для создания новых токенов мы используем jwt.NewWithClaims
функцию.
package main import ( "fmt" "log" "github.com/golang-jwt/jwt/v4" ) const key = "my secure jwt key" func main() { token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.RegisteredClaims{}) jwtToken, err := token.SignedString([]byte(key)) if err != nil { log.Fatal(err) } fmt.Printf("JWT Token: %s\n", jwtToken) } main.go
Позвольте рассказать вам об этом:
- NewWithClaims принимает два параметра: метод подписи и утверждения . Утверждения — это фактические данные, которые будет содержать токен JWT.
- jwt.NewWithClaims не создает новый токен, вам нужно вызвать
SignedString
функцию, передав ей секретный ключ , чтобы получить фактический токен JWT. - jwt.RegisteredClaims — это общие/стандартные утверждения JWT, которые обычно присутствуют в полезной нагрузке токена JWT, например
iat
(время выпуска токена),exp
(время истечения срока действия токена) и многие другие.
Создание токена с данными
Код до сих пор создает токен JWT, но не содержит никаких данных, предоставленных пользователем. Это просто: вместо предоставления jwt.RegisteredClaims
в качестве полезной нагрузки вы встраиваете jwt.RegisteredClaims
другую структуру с дополнительной информацией, назовем ее UserClaim
.
type UserClaim struct { jwt.RegisteredClaims ID int Email string Name string }
Используйте UserClaim
как второй аргумент функции jwt.NewWithClaims
.
token := jwt.NewWithClaims(jwt.SigningMethodHS256, UserClaim{ RegisteredClaims: jwt.RegisteredClaims{}, ID: "1", Email: "email@email.com", Name: "First Last", })
Мы собираемся провести рефакторинг процесса создания токена JWT в отдельную функцию под названием CreateJWTToken
, ниже приведен полный код.
package main import ( "fmt" "log" "github.com/golang-jwt/jwt/v4" ) const key = "my secure jwt key" // Data that will be in the token type UserClaim struct { jwt.RegisteredClaims ID int Email string Name string } func main() { jwtToken, err := CreateJWTToken(1, "email@email.com", "First Last") if err != nil { log.Fatal(err) } fmt.Printf("JWT Token: %s\n", jwtToken) } // 👇 func CreateJWTToken(id int, email string, name string) (string, error) { token := jwt.NewWithClaims(jwt.SigningMethodHS256, UserClaim{ RegisteredClaims: jwt.RegisteredClaims{}, ID: id, Email: email, Name: name, }) // Create the actual JWT token signedString, err := token.SignedString([]byte(key)) if err != nil { return "", fmt.Errorf("error creating signed string: %v", err) } return signedString, nil } main.go
Анализ токена JWT
Анализ токенов JWT и извлечение из них данных можно выполнить с помощью функции jwt.ParseWithClaims
(есть еще одна функция jwt.Parse
, которая позволит вам просто проанализировать и проверить, действителен ли токен).
var jwtToken string // a token generated from previous code var userClaim UserClaim token, err := jwt.ParseWithClaims(jwtToken, &userClaim, func(token *jwt.Token) (interface{}, error) { return []byte(key), nil })
Более полный рабочий пример анализа токена JWT.
package main import ( "fmt" "log" "github.com/golang-jwt/jwt/v4" ) const key = "my secure jwt key" type UserClaim struct { jwt.RegisteredClaims ID int Email string Name string } func main() { jwtToken := "a token generated from previous code" var userClaim UserClaim // 👇 token, err := jwt.ParseWithClaims(jwtToken, &userClaim, func(token *jwt.Token) (interface{}, error) { return []byte(key), nil }) if err != nil { log.Fatal(err) } // Checking token validity if !token.Valid { log.Fatal("invalid token") } fmt.Printf("Parsed User Claim: %d %s %s\n", userClaim.ID, userClaim.Email, userClaim.Name) } main.go
Здесь следует обратить внимание на то, как jwt.ParseWithClaims
принимает секретный ключ: в качестве третьего аргумента он принимает функцию, в которой вы должны вернуть ключ.
Вы можете проверить достоверность токена, используя Valid
логическое значение.
Если токен действителен, UserClaim
он будет заполнен информацией внутри токена.