[Golang]JWT主要函数汇总

前言

  • 最近在学token,了解到jwt相关的函数与方法,于是乎准备汇总一下最近学到的内容。
  • 当然,这次汇总并不全面,只是涉及到了部分重要函数。

一、生成JWT

1、NewWithClaims函数

  • 核心功能:它是创建 JWT 的关键起始点。此函数用于构建一个新的 JWT 结构体实例,需要传入两个主要参数,一个是签名方法(比如jwt.SigningMethodHS256),另一个是声明(Claims)。签名方法指定了用于生成 JWT 签名的算法类型,常见的有 HMAC - SHA256(SigningMethodHS256)等。声明部分包含了要在 JWT 中传递的信息,例如用户 ID、角色、过期时间等。
  • 示例说明
claims := jwt.MapClaims{}
claims["sub"] = "1234567890"
claims["name"] = "John Doe"
claims["iat"] = time.Now().Unix()
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)

在这个例子中,首先创建了一个MapClaims类型的claims对象,它本质上是一个map[string]interface{}。然后向其中添加了用户 ID(sub)、姓名(name)和签发时间(iat)等信息。接着使用NewWithClaims函数创建了一个新的 JWT,指定签名方法为HS256,将claims作为声明部分传入。

2、SignedString函数

  • 功能核心:在使用NewWithClaims创建 JWT 结构体后,SignedString函数用于对 JWT 进行签名并生成最终的 JWT 字符串。它接受一个字节切片作为参数,这个字节切片代表用于签名的密钥。密钥的安全性至关重要,因为它用于确保 JWT 的完整性和真实性。
  • 示例说明
signedToken, err := token.SignedString([]byte("my_secret_key"))
if err!= nil {
    fmt.Println("签名出错:", err)
    return
}
fmt.Println("生成的JWT:", signedToken)

这里将之前创建的token(通过NewWithClaims函数得到)使用SignedString函数进行签名。传入字节切片形式的密钥[]byte("my_secret_key"),如果签名过程没有错误,就会得到最终的 JWT 字符串signedToken,可以将这个字符串发送给客户端用于后续的身份验证等操作。

二、解析JWT

1、Parse函数

  • 功能核心:用于解析一个 JWT 字符串,尝试将其分解为头部载荷签名,并验证签名的有效性。它接受两个主要参数,一个是要解析的 JWT 字符串,另一个是一个函数,这个函数用于返回验证签名所需的密钥。在解析过程中,它会检查 JWT 的格式是否正确,并且根据提供的密钥验证签名是否被篡改。
  • 示例说明
tokenString := "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"
token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
    return []byte("my_secret_key"), nil
})
if err!= nil {
    fmt.Println("解析出错:", err)
    return
}

在这个示例中,给定一个 JWT 字符串tokenString,使用Parse函数进行解析。在第二个参数的函数中,返回了字节切片形式的密钥[]byte("my_secret_key")用于签名验证。如果解析过程中出现错误,例如 JWT 格式错误或者签名验证失败,err就不会为nil,可以根据err进行相应的错误处理。

2、ParseWithClaims函数

  • 功能核心:与Parse函数类似,但它更侧重于将解析后的声明(Claims)直接转换为指定的类型。这在需要直接访问和使用 JWT 载荷中的声明信息时非常有用。它接受三个主要参数,第一个是 JWT 字符串,第二个是用于存储声明的变量(需要实现Claims接口),第三个是一个函数用于返回验证签名所需的密钥。
  • 示例说明
claims := jwt.MapClaims{}
_, err := jwt.ParseWithClaims(tokenString, &claims, func(token *jwt.Token) (interface{}, error) {
    return []byte("my_secret_key"), nil
})
if err!= nil {
    fmt.Println("解析出错:", err)
    return
}
fmt.Println("用户ID:", claims["sub"])

这里首先创建了一个MapClaims类型的claims变量,然后使用ParseWithClaims函数将tokenString解析后的声明存储到claims变量中。如果解析成功且签名验证通过,就可以像访问普通的map一样从claims中获取载荷中的信息,如示例中的用户 ID(sub)。

三、验证JWT

1、Validate函数

  • 功能核心:虽然ParseParseWithClaims函数在解析过程中会验证签名,但在实际应用中,可能还需要对 JWT 中的声明进行更多自定义的验证,例如检查过期时间、权限范围等。这就需要自定义一个验证函数,在这个函数中可以综合使用ParseParseWithClaims以及其他逻辑来进行全面的 JWT 验证。
  • 示例说明
func validateToken(token *jwt.Token, claims jwt.Claims, secretKey []byte) bool {
    // 验证签名
    _, err := jwt.ParseWithClaims(token.Raw, claims, func(t *jwt.Token) (interface{}, error) {
        return secretKey, nil
    })
    if err!= nil {
        return false
    }
    // 可以添加更多自定义的声明验证逻辑,比如检查过期时间
    if exp, ok := claims.(jwt.MapClaims)["exp"].(float64); ok {
        if int64(exp) < time.Now().Unix() {
            return false
        }
    }
    return true
}

在这个自定义的validateToken函数中,首先通过ParseWithClaims验证 JWT 的签名。然后,通过类型断言检查声明中的过期时间(exp)是否存在并且是否已经过期(将其转换为int64后与当前时间的Unix时间戳进行比较)。可以根据实际需求在这个函数中添加更多的验证逻辑,比如检查权限相关的声明等,以确保 JWT 的完整性和合法性满足应用程序的要求。

结语

  • JWT相关的函数其实并不多,只是有些稍微有点费解。
  • 本文大部分引自ai(现在的ai真的太好用了),这里主要是汇总这部分知识。
  • 希望这篇文章能够帮到你。

你可能感兴趣的:(golang,开发语言,中间件,后端,mysql)