Skip to content

Golang学习笔记-jwt

简介

参考地址:https://jwt.io/

JWT全称json web token,是目前主流的跨域认证解决方案之一

JWT的原理:在服务器认证以后生成3个Json对象,将这3个对象分别通过base64编码,将编码后的结果根据页眉中声明的加密方式进行签名,最终以. 作为分隔符组合成一个字符串返回给用户。它分为三部分:页眉有效载荷签名,这三部分中间由3个.分割,最终的数据格式是 页眉.有效负荷.签名

页眉:由令牌类型令牌的签名算法 组成 有效载荷:由已注册公共私有声明组成,

签名:签名部分根据页眉中的签名算法、密钥以及有效载荷生成

栗子

package main

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

type MyCustomClaims struct {
    UserID     int
    Username   string
    GrantScope string
    jwt.RegisteredClaims
}

// 签名密钥
const sign_key = "hello jwt"

// 随机字符串
var letters = []rune("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")

func randStr(str_len int) string {
    rand_bytes := make([]rune, str_len)
    for i := range rand_bytes {
        rand_bytes[i] = letters[rand.Intn(len(letters))]
    }
    return string(rand_bytes)
}

func generateTokenUsingHs256() (string, error) {
    claim := MyCustomClaims{
        UserID:     000001,
        Username:   "Tom",
        GrantScope: "read_user_info",
        RegisteredClaims: jwt.RegisteredClaims{
            Issuer:    "jruing",                                        // 签发者
            Subject:   "zhangsan",                                      // 签发对象
            Audience:  jwt.ClaimStrings{"Android_APP", "IOS_APP"},      //签发受众
            ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Hour)),   //过期时间
            NotBefore: jwt.NewNumericDate(time.Now().Add(time.Second)), //最早使用时间
            IssuedAt:  jwt.NewNumericDate(time.Now()),                  //签发时间
            ID:        randStr(10),                                     // wt ID, 类似于盐值
        },
    }
    token, err := jwt.NewWithClaims(jwt.SigningMethodHS256, claim).SignedString([]byte(sign_key))
    return token, err
}

func parseTokenHs256(token_string string) (*MyCustomClaims, error) {
    token, err := jwt.ParseWithClaims(token_string, &MyCustomClaims{}, func(token *jwt.Token) (interface{}, error) {
        return []byte(sign_key), nil //返回签名密钥
    })
    if err != nil {
        return nil, err
    }

    if !token.Valid {
        return nil, errors.New("claim invalid")
    }

    claims, ok := token.Claims.(*MyCustomClaims)
    if !ok {
        return nil, errors.New("invalid claim type")
    }

    return claims, nil
}

func main() {
    // 生成jwt token
    token, err := generateTokenUsingHs256()
    if err != nil {
        panic(err)
    }
    fmt.Println("Token = ", token)

    time.Sleep(time.Second * 2)
    // 解析jw ttoken
    my_claim, err := parseTokenHs256(token)
    if err != nil {
        panic(err)
    }
    fmt.Println("my claim = ", my_claim)

}