Golang实现JWT身份验证的示例详解

admin 轻心小站 关注 LV.19 运营
发表于Go语言交流版块 教程

JSON Web Token(JWT)是一种开放标准(RFC 7519),用于在双方之间安全地传输信息作为JSON对象。这个信息可以被验证和信任,因为它是经过数字签名的。JWT可以使用密钥(使用HMA

JSON Web Token(JWT)是一种开放标准(RFC 7519),用于在双方之间安全地传输信息作为JSON对象。这个信息可以被验证和信任,因为它是经过数字签名的。JWT可以使用密钥(使用HMAC算法)或使用RSA或ECDSA的公钥/私钥对进行签名。

在Go语言中,可以使用jwt-go这个流行的第三方库来实现JWT身份验证。以下是一个使用JWT进行身份验证的基本示例,包括创建、验证和解析JWT。

安装jwt-go库

首先,你需要安装jwt-go库。在你的Go项目目录下,运行以下命令:

go get github.com/dgrijalva/jwt-go

创建JWT

以下代码示例展示了如何创建一个JWT:

package main

import (
	"fmt"
	"time"

	"github.com/dgrijalva/jwt-go"
)

func main() {
	// 定义签名的密钥
	secretKey := []byte("my_secret_key")

	// 设置过期时间
	expirationTime := time.Now().Add(5 * time.Minute)

	// 创建JWT的claims
	claims := &jwt.MapClaims{
		"username": "johndoe",
		"exp":      expirationTime.Unix(),
		"iat":      time.Now().Unix(),
	}

	// 使用HS256算法创建JWT
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)

	// 使用密钥签名JWT
	tokenString, err := token.SignedString(secretKey)
	if err != nil {
		fmt.Println("Error creating JWT:", err)
		return
	}

	fmt.Println("JWT:", tokenString)
}

在这个例子中,我们创建了一个包含用户名和过期时间的JWT。jwt.NewWithClaims函数用于创建一个新的JWT,其中包含了我们自定义的claims。然后,我们使用SignedString方法和我们的密钥对JWT进行签名。

验证JWT

验证JWT的过程包括使用相同的密钥和签名方法来验证JWT的签名是否有效,并检查其claims是否符合预期:

func verifyJWT(tokenString string, secretKey []byte) (*jwt.MapClaims, error) {
	token, err := jwt.ParseWithClaims(tokenString, &jwt.MapClaims{}, func(token *jwt.Token) (interface{}, error) {
		// 使用HS256算法来验证签名
		return secretKey, nil
	})

	if err != nil {
		return nil, err
	}

	if token.Valid {
		claims, ok := token.Claims.(*jwt.MapClaims)
		if !ok {
			return nil, fmt.Errorf("token claims are not of type *jwt.MapClaims")
		}
		return claims, nil
	}

	return nil, fmt.Errorf("token is not valid")
}

在这个函数中,我们使用jwt.ParseWithClaims方法来解析JWT,并提供一个用于验证签名的函数。如果JWT的签名有效,并且claims没有过期,token.Valid将会是true。

解析JWT

解析JWT通常意味着从JWT中提取信息。这可以通过验证JWT后,获取其claims来实现:

func parseJWT(tokenString string, secretKey []byte) (*jwt.MapClaims, error) {
	claims, err := verifyJWT(tokenString, secretKey)
	if err != nil {
		return nil, err
	}

	// 从claims中提取用户名
	if username, ok := claims["username"].(string); ok {
		fmt.Printf("Username: %s\n", username)
	}

	return claims, nil
}

在这个函数中,我们调用了verifyJWT函数来验证JWT,然后从claims中提取了用户名。

完整示例

结合以上代码,我们可以创建一个完整的JWT身份验证示例:

package main

import (
	"fmt"
	"time"

	"github.com/dgrijalva/jwt-go"
)

func main() {
	// 创建JWT
	secretKey := []byte("my_secret_key")
	tokenString, err := createJWT("johndoe", secretKey)
	if err != nil {
		fmt.Println("Error creating JWT:", err)
		return
	}

	// 验证JWT
	claims, err := verifyJWT(tokenString, secretKey)
	if err != nil {
		fmt.Println("Error verifying JWT:", err)
		return
	}

	// 解析JWT
	err = parseJWT(tokenString, secretKey)
	if err != nil {
		fmt.Println("Error parsing JWT:", err)
		return
	}

	fmt.Println("JWT is valid and parsed successfully.")
}

// createJWT 创建并签名一个新的JWT
func createJWT(username string, secretKey []byte) (string, error) {
	expirationTime := time.Now().Add(5 * time.Minute)
	claims := &jwt.MapClaims{
		"username": username,
		"exp":      expirationTime.Unix(),
		"iat":      time.Now().Unix(),
	}
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
	return token.SignedString(secretKey)
}

// verifyJWT 验证JWT的有效性
func verifyJWT(tokenString string, secretKey []byte) (*jwt.MapClaims, error) {
	token, err := jwt.ParseWithClaims(tokenString, &jwt.MapClaims{}, func(token *jwt.Token) (interface{}, error) {
		return secretKey, nil
	})
	if err != nil {
		return nil, err
	}
	if token.Valid {
		claims, ok := token.Claims.(*jwt.MapClaims)
		if !ok {
			return nil, fmt.Errorf("token claims are not of type *jwt.MapClaims")
		}
		return claims, nil
	}
	return nil, fmt.Errorf("token is not valid")
}

// parseJWT 从JWT中提取信息
func parseJWT(tokenString string, secretKey []byte) (*jwt.MapClaims, error) {
	claims, err := verifyJWT(tokenString, secretKey)
	if err != nil {
		return nil, err
	}
	if username, ok := claims["username"].(string); ok {
		fmt.Printf("Username: %s\n", username)
	}
	return claims, nil
}

在这个完整的示例中,我们首先创建了一个JWT,然后验证了它的有效性,并从中提取了用户名。这个过程展示了JWT在身份验证中的典型用法。

文章说明:

本文原创发布于探乎站长论坛,未经许可,禁止转载。

题图来自Unsplash,基于CC0协议

该文观点仅代表作者本人,探乎站长论坛平台仅提供信息存储空间服务。

评论列表 评论
发布评论

评论: Golang实现JWT身份验证的示例详解

粉丝

0

关注

0

收藏

0

已有0次打赏