在 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网站上进行查看,使用公钥进行签名校验,如图:
网友评论