Go Jwt Token 使用 RSA256 签名

在 Go 语言中使用 Jwt Token ,我们采用更加安全的RAS256方式进行签名。使用私钥进行签发 Token,使用公钥进行签名验证。

生成密钥对

在项目根目录下面创建 Makefile文件,填充下面的内容:

.PHONY: cert-private cert-public
cert-private:
    @openssl genrsa -out cert/id_rsa 4096
cert-public:
    @openssl rsa -in cert/id_rsa -pubout -out cert/id_rsa_2.pub

在 Shell 中执行:

make cert-private && make cert-public

来生成对应的私钥和公钥

使用下面的代码来创建main.go 文件:

package main

import (
    "bytes"
    "fmt"
    "log"
    "os"
    "time"

    "github.com/golang-jwt/jwt/v5"
    "github.com/google/uuid"
)

var (
    privateKey *bytes.Buffer
    publicKey  *bytes.Buffer
)

func generateToken() (string, error) {
    key, err := jwt.ParseRSAPrivateKeyFromPEM(privateKey.Bytes())
    if err != nil {
        return "", err
    }
    now := time.Now().UTC()
    claims := jwt.RegisteredClaims{
        IssuedAt:  jwt.NewNumericDate(now),
        ID:        uuid.NewString(),
        ExpiresAt: jwt.NewNumericDate(now.Add(10 * time.Minute)),
    }
    token, err := jwt.NewWithClaims(jwt.SigningMethodRS256, claims).SignedString(key)
    if err != nil {
        return "", err
    }
    return token, nil
}

func validate(token string) (map[string]interface{}, error) {
    key, err := jwt.ParseRSAPublicKeyFromPEM(publicKey.Bytes())
    if err != nil {
        return nil, err
    }
    parsed, err := jwt.Parse(token, func(jwtToken *jwt.Token) (interface{}, error) {
        if _, ok := jwtToken.Method.(*jwt.SigningMethodRSA); !ok {
            return nil, fmt.Errorf("unexpected method:%s", jwtToken.Header["alg"])
        }
        return key, nil
    })
    if err != nil {
        return nil, err
    }

    claims, ok := parsed.Claims.(jwt.MapClaims)
    if !ok || !parsed.Valid {
        return nil, fmt.Errorf("invalid token:%w", err)
    }
    return claims, nil
}

func main() {
    prKey, err := os.ReadFile("cert/id_rsa")
    if err != nil {
        log.Fatal(err)
    }
    privateKey = bytes.NewBuffer(prKey)

    pubKey, err := os.ReadFile("cert/id_rsa.pub")
    if err != nil {
        log.Fatal(err)
    }
    publicKey = bytes.NewBuffer(pubKey)
    token, err := generateToken()
    if err != nil {
        log.Fatal(err)
    }
    log.Printf("token:%s", token)
    m, err := validate(token)
    if err != nil {
        log.Fatal(err)
    }
    log.Printf("token claims:%v", m)
}

编译执行:

go run main.go

生成的 Token 可以在jwt.io网站上进行查看,使用公钥进行签名校验,如图:

image.png

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。