提示:非常简单,建议别看
目录
前言
接下来是对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)
}
到此结束!!!