SoFunction
Updated on 2025-03-05

Analysis of jwt usage tutorial flow in golang

golang-jwt use

Old version <v4.0.0 is /dgrijalva/jwt-go New version /golang-jwt/jwt

This article environment is a new version

encryption

1. We should install and import it before using it

go get -u /golang-jwt/jwt/v4
import "/golang-jwt/jwt/v4"

2. Since the import is successful, start using it

package main
import (
   "fmt"
   "/golang-jwt/jwt/v4"
)
func main() {
    // Create a key   	key := []byte("aaa")
    // Create a Token structure	claims := (jwt.SigningMethodHS256, {
		"user": "zhangshan",
		"pass": "123123",
	})
    // Call the encryption method and use the Token string	signingString, err := (key)
	if err != nil {
		return
	}
	(signingString)
}
//This is the output result&amp;{ 0xc0000c2690 map[alg:ES256 typ:JWT] map[user:zhangshan]  false}
// This is the encrypted stringeyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJwYXNzIjoiMTIzMTIzIiwidXNlciI6InpoYW5nc2hhbiJ9.-2-xIJXMGKV-GyhM24OKbDVqWs4dsIANBsGhzXEfEFM

3. Explain step by step

First, let's check the first step

claims := (jwt.SigningMethodES256, {
      "user": "zhangshan",
   })

newWithClaims will return a Token structure, and this token structure has the following properties

type Token struct {
   Raw       string        //Original token   Method    SigningMethod   // Encryption methods such as sha256 encryption   Header    map[string]interface{} // token header information   Claims    Claims  // Encryption configuration, such as timeout, etc.   Signature string  // Encrypted string   Valid     bool   // Whether to verify}
type Token struct {
   Raw       string        //Original token   Method    SigningMethod   // Encryption methods such as sha256 encryption   Header    map[string]interface{} // token header information   Claims    Claims  // Encryption configuration, such as timeout, etc.   Signature string  // Encrypted string   Valid     bool   // Whether to verify}

We can obtain the encrypted string information through this structure.

Next, we need to explain the Claims structure that stores the timeout time and other information of the token string and the token verification work during parsing.

type Claims interface {
   Valid() error
}
//Implementation classes include MapClaims, RegisteredClaims, StandardClaims (discarded)//In fact, the last two structures are written based on MapClaims, so we only need to master MapClaimstype MapClaims map[string]interface{}

It is a map collection, but it implements the above Valid() method, which implements verification of the token expiration date, release time, and effective time.
soThere are three fixed keys in the map that we can set as neededexp expiration time, iat release time, nbf effective time

Decryption

Since the token value has been encrypted, how to verify it (commonly known as decryption)?

// Parse into Claims structure according to Token string_, err = (signingString, {}, func(token *) (interface{}, error) {
   ()
   return []byte("aaa"), nil
})
if err != nil {
   (err)
   return
}

In this method, there are four parameters. We need to pay attention to the third method parameter. This type is a method. Token is used as a parameter and two return values. We focus on the first return value. This value will be used for encoding and parsing, so we need to pass in the key key in the above.

The fourth parameter is a configuration parameter, which mainly controls the verification work of the token during parse. For example, calling WithoutClaimsValidation() will close the token's expiration check and other operations.

WithValidMethods(methods []string)  //Specify the decryption algorithm used, it will compare the name with the encryption method in token, and if false, it will return the error valueWithoutClaimsValidation() // Ignore expirations、Release time and other inspections

Source code analysis

Next we will explain the specific process

SignedString

SignedString is used to generate token structure

func (t *Token) SignedString(key interface{}) (string, error) {
   var sig, sstr string
   var err error
   // Encrypt header and claims via base64   if sstr, err = (); err != nil {
      return "", err
   } 
   // Encrypt according to the key value through the specified encryption method   if sig, err = (sstr, key); err != nil {
      return "", err
   }
   // Stitching token string   return ([]string{sstr, sig}, "."), nil
}

ParseWithClaims

ParseWithClaims is used to parse the token string and return to the token structure

func ParseWithClaims(tokenString string, claims Claims, keyFunc Keyfunc, options ...ParserOption) (*Token, error) {
   // Create a parser,   //ParseWithClaims parses the token string   return NewParser(options...).ParseWithClaims(tokenString, claims, keyFunc)
}
func (p *Parser) ParseWithClaims(tokenString string, claims Claims, keyFunc Keyfunc) (*Token, error) {
    // parse the string, cut according to ., decode it through base64, and obtain encryption methods such as sha256 according to the alg attribute in the header    // The return value token is a Token structure, and parts are an array after string cutting	token, parts, err := (tokenString, claims)
	if err != nil {
		return token, err
	}
	// Determine whether to specify a verification method	if  != nil {
		var signingMethodValid = false
		var alg = ()
		for _, m := range  {
			if m == alg {
				signingMethodValid = true
				break
			}
		}
		if !signingMethodValid {
			// The specified method is inconsistent with the method in token			return token, NewValidationError(("signing method %v is invalid", alg), ValidationErrorSignatureInvalid)
		}
	}
	// Get the key key	var key interface{}
    // Determine whether keyfunc is implemented, which is the third parameter	if keyFunc == nil {
		// keyFunc was not provided.  short circuiting validation
		return token, NewValidationError("no Keyfunc was provided.", ValidationErrorUnverifiable)
	}
    // Call the method and return the key value	if key, err = keyFunc(token); err != nil {
		// keyFunc returned an error
		if ve, ok := err.(*ValidationError); ok {
			return token, ve
		}
		return token, &amp;ValidationError{Inner: err, Errors: ValidationErrorUnverifiable}
	}
	vErr := &amp;ValidationError{}
	// To determine whether to perform verification, SkipClaimsValidation is false by default plus!  Become true	if ! {
		if err := (); err != nil {
			// If the Claims Valid returned an error, check if it is a validation error,
			// If it was another error type, create a ValidationError with a generic ClaimsInvalid flag set
			if e, ok := err.(*ValidationError); !ok {
				vErr = &amp;ValidationError{Inner: err, Errors: ValidationErrorClaimsInvalid}
			} else {
				vErr = e
			}
		}
	}
	// Perform signature verification	 = parts[2]
	if err = ((parts[0:2], "."), , key); err != nil {
		 = err
		 |= ValidationErrorSignatureInvalid
	}
	if () {
		 = true
		return token, nil
	}
	return token, vErr
}

This is the end of this article about the tutorial on using jwt in golang. For more related content on using golang, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!