github.com/binbinly/pkg@v0.0.11-0.20240321014439-f4fbf666eb0f/auth/jwt.go (about)

     1  package auth
     2  
     3  import (
     4  	"context"
     5  	"time"
     6  
     7  	"github.com/golang-jwt/jwt/v5"
     8  )
     9  
    10  // Payload is the data of the JSON web token.
    11  // 主要是配合jwt来生成用户登录token
    12  type Payload struct {
    13  	UserID int
    14  }
    15  
    16  // secretFunc validates the secret format.
    17  func secretFunc(secret string) jwt.Keyfunc {
    18  	return func(token *jwt.Token) (any, error) {
    19  		// Make sure the `alg` is what we except.
    20  		if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
    21  			return nil, jwt.ErrSignatureInvalid
    22  		}
    23  
    24  		return []byte(secret), nil
    25  	}
    26  }
    27  
    28  // Parse validates the token with the specified secret,
    29  // and returns the payloads if the token was valid.
    30  func Parse(tokenString string, secret string) (*Payload, error) {
    31  	// Parse the token.
    32  	token, err := jwt.Parse(tokenString, secretFunc(secret))
    33  	if err != nil {
    34  		return nil, err
    35  	}
    36  	// Read the token if it's valid.
    37  	if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
    38  		payloads := &Payload{}
    39  		payloads.UserID = int(claims["user_id"].(float64))
    40  		return payloads, nil
    41  	}
    42  
    43  	// Other errors.
    44  	return nil, err
    45  }
    46  
    47  // Sign signs the payload with the specified secret.
    48  func Sign(ctx context.Context, payload map[string]any, secret string, timeout int64) (tokenString string, err error) {
    49  	// The token content.
    50  	// iss: (Issuer)签发者
    51  	// iat: (Issued At)签发时间,用Unix时间戳表示
    52  	// exp: (Expiration Time)过期时间,用Unix时间戳表示
    53  	// aud: (Audience)接收该JWT的一方
    54  	// sub: (Subject)该JWT的主题
    55  	// nbf: (Not Before)不要早于这个时间
    56  	// jti: (JWT ID)用于标识JWT的唯一ID
    57  	now := time.Now().Unix()
    58  	claims := make(jwt.MapClaims)
    59  	claims["nbf"] = now
    60  	claims["iat"] = now
    61  	claims["exp"] = now + timeout
    62  
    63  	for k, v := range payload {
    64  		claims[k] = v
    65  	}
    66  
    67  	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
    68  
    69  	// Sign the token with the specified secret.
    70  	tokenString, err = token.SignedString([]byte(secret))
    71  
    72  	return
    73  }