JSON Web Token 的学习记录

提示:非常简单,建议别看


前言

接下来是对JWT(json web token)的一个简单学习,有不足希望评论补充

在下面我将会对HS256 和 RSA 是两种不同的数字签名算法来实现Jwt进行一个介绍和实现


一、JWT是什么?

JSON Web Token (JWT)是一个开放标准(RFC 7519),它定义了一种紧凑的、自包含的方式,用于作为JSON对象在各方之间安全地传输信息。该信息可以被验证和信任,因为它是数字签名的。

二、HS256 和 RSA签名算法

1.HS256

HS256(HMAC SHA-256)是一种对称加密签名算法,广泛用于生成和验证 JWT(JSON Web Token)。它使用单个密钥进行加密和解密,确保数据完整性和认证。

  • 类型:对称加密
  • 密钥管理:使用相同的密钥进行签名和验证,发送方和接收方必须共享该密钥。
  • 消息哈希:将头部和负载与密钥结合,使用 SHA-256 哈希算法生成哈希值。
  • 签名:将哈希值附加到 JWT 的最后,形成完整的 JWT。

优缺点:

优点:
  • 简单高效:计算速度快,适合高并发场景。

  • 适合小规模应用:密钥管理相对简单。

缺点:
  • 密钥安全:密钥一旦泄露,攻击者可伪造有效的 JWT。
  • 不支持分布式环境:不适合需要多个服务验证的场景。 

2.RSA

RSA(Rivest-Shamir-Adleman)是一种非对称加密算法,广泛用于数据加密和数字签名。它基于大素数分解的数学难题,确保安全性。

  • 类型:非对称加密
  • 密钥管理:使用一对密钥:公钥和私钥。私钥用于签名,公钥用于验证。

优缺点:

  • 优点

    • 具备较高的安全性,公钥和私钥分离。
    • 广泛应用,支持多种标准。
  • 缺点

    • 加密和解密速度较慢。
    • 对于大数据,通常只用于加密对称密钥

三、代码部分

    

  1.引用包:

import (
	"crypto/rsa"
	"crypto/x509"
	"encoding/pem"
	"fmt"
	"github.com/golang-jwt/jwt/v4"
	"io/ioutil"
	"log"
	"time"
)

 2.生成Jwt(RSA)

// 生成token
func GetJwtToken(payload string, private *rsa.PrivateKey) (string, error) {
	//创建了一个新的 jwt.MapClaims 类型的变量
	claims := make(jwt.MapClaims)
	//当前时间
	iat := time.Now().Unix()
	//过期时间
	claims["exp"] = iat + seconds
	//生效时间
	claims["iat"] = iat
	// 自定义字段  我们存储的数据
	claims["payload"] = payload
	//使用 HS256 签名算法创建一个新的 JWT 对象
	token := jwt.New(jwt.SigningMethodRS256)
	//claims 是一个 jwt.MapClaims 类型的对象,它包含了 JWT 的过期时间(exp)、生效时间(iat)和自定义的 payload 字段。
	//将自定义的声明(Claims)设置到 JWT 对象中
	token.Claims = claims
	//使用私钥对 JWT 对象进行签名,生成一个 JWT 字符串
	return token.SignedString(private)
}

3.解析Jwt

// 解析token
func ParseJwToken(tokenString string, publicKey *rsa.PublicKey) (string, error) {
	// 尝试解析传入的JWT字符串,使用提供的密钥进行验证
	token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
		// 返回用于验证签名的密钥
		return publicKey, nil
	})
	// 如果解析成功且JWT有效,则提取自定义声明字段'payload'的值
	if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
		// 提取payload字段的值并返回,如果提取失败则返回error
		return claims["payload"].(string), nil
	}
	return "", err
}

4.从本地获取私钥PrivateKey

// 加载私钥
func LoadPrivate() (*rsa.PrivateKey, error) {
	// 读取私钥文件
	file, err := ioutil.ReadFile("private.pem")
	if err != nil {
		return nil, fmt.Errorf(err.Error())
	}
	// 从包含PEM编码的私钥文件中解码出私钥
	p, _ := pem.Decode(file)
	// 检查解码是否成功,以及解码出的是否是RSA私钥
	if p == nil || p.Type!= "RSA PRIVATE KEY" {
		// 如果解码失败或类型不正确,返回错误
		return nil, fmt.Errorf("failed to parse private key")
	}
	// 将解码后的私钥解析为PKCS8格式的RSA私钥
	pub, err := x509.ParsePKCS8PrivateKey(p.Bytes)
	// 如果解析过程中发生错误,返回错误
	if err!= nil {
		return nil, err
	}
	return pub.(*rsa.PrivateKey), nil
}

5.从本地加载公钥PublicKey

// 加载公钥
func LoadPublicKey() (*rsa.PublicKey, error) {
	// 读取公钥文件
	file, err := ioutil.ReadFile("public.pem")
	if err != nil {
		return nil, fmt.Errorf(err.Error())
	}
	p, _ := pem.Decode(file)
	if p == nil || p.Type != "PUBLIC KEY" {
		return nil, fmt.Errorf("failed to parse public key")
	}
	pub, err := x509.ParsePKIXPublicKey(p.Bytes)
	if err != nil {
		return nil, fmt.Errorf(err.Error())
	}
	return pub.(*rsa.PublicKey), nil
}

6.入口文件main.go

func main() {
	private, err := LoadPrivate()
	if err != nil {
		fmt.Println("加载私钥失败", err)
		return
	}
	publicKey, err := LoadPublicKey()
	if err != nil {
		log.Fatalf("加载公钥失败: %v", err)
	}
	payload := "这是我的有效负载"
	token, err := GetJwtToken(payload, private)
	if err != nil {
		log.Fatalf("生成JWT失败: %v", err)
		return
	}
	fmt.Println("生成的JWT:", token)
	// 解析JWT
	parsedPayload, err := ParseJwToken(token, publicKey)
	if err != nil {
		log.Fatalf("解析JWT失败: %v", err)
	}
	fmt.Println("解析的负载:", parsedPayload)
}

最后是我们的一个运行效果:


总结

本文简单介绍了一下HS256 和 RSA签名算法,以及jwt的一个使用(RSA签名算法生成)

代码部分只对RSA进行了实现。

对于HS256:

相对于RSA算法,少来对于私钥和公钥的一个获取;HS256使用相同的密钥进行签名和验证,发送方和接收方必须共享该密钥。

下面是一个使用HS256算法的一个Jwt生成:

const (
	//私钥
	secretKey = "private_key "
	// 过期时间 1天
	seconds = 86400
)

// 生成token
func GetJwtToken(payload string) (string, error) {
	//创建了一个新的 jwt.MapClaims 类型的变量
	claims := make(jwt.MapClaims)
	//当前时间
	iat := time.Now().Unix()
	//过期时间
	claims["exp"] = iat + seconds
	//生效时间
	claims["iat"] = iat
	// 自定义字段  我们存储的数据
	claims["payload"] = payload
	//使用 HS256 签名算法创建一个新的 JWT 对象
	token := jwt.New(jwt.SigningMethodHS256)
	//claims 是一个 jwt.MapClaims 类型的对象,它包含了 JWT 的过期时间(exp)、生效时间(iat)和自定义的 payload 字段。
	//将自定义的声明(Claims)设置到 JWT 对象中
	token.Claims = claims
	//使用私钥对 JWT 对象进行签名,生成一个 JWT 字符串
	return token.SignedString(secretKey)
}

  到此结束!!!                                                

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值