JWT,即JSON Web Token,是一种用于在网络应用间传递信息的开放标准(RFC 7519)。它通过使用JSON对象作为令牌的载荷,将一些声明(claims)编码到令牌中,并使用数字签名(或加密)对令牌进行验证和安全传输。JWT通常被用于实现身份认证和授权机制。
JWT由三部分组成:
- Header(头部) : 包含令牌的类型和使用的签名算法等信息,通常由两部分组成,第一部分是
alg表示签名算法,第二部分是typ表示令牌类型。然后将头部进行Base64编码,形成JWT的第一部分。 - Payload(载荷) : 包含称为声明(claims)的信息。声明分为三种类型:注册声明(registered claims)、公共声明(public claims)和私有声明(private claims)。注册声明包括一些预定义的标准声明,如发行人(issuer)、过期时间(expiration time)、主题(subject)等。公共声明可以根据需要自定义,但是建议遵循某种约定,以避免冲突。私有声明是用户自定义的声明。载荷也会被Base64编码,形成JWT的第二部分。
- Signature(签名) : 将编码后的头部和载荷、一个密钥,使用指定的签名算法进行签名。签名的目的是确保令牌的完整性和真实性。签名的结果会被附加到JWT的最后一部分。
完整的JWT格式为header.payload.signature,各部分之间用.分隔。
JWT的主要优势之一是它的可扩展性和自包含性,因为所有的信息都包含在令牌中,无需在服务器端存储会话信息。但也要注意,JWT默认情况下是不加密的,只是使用签名保证完整性,因此不应将敏感信息存储在JWT中。
以下是一个用Golang创建和验证JWT的简单示例:
package main
import (
"fmt"
"time"
"github.com/dgrijalva/jwt-go"
)
func main() {
// 创建一个JWT
token := createJWT("mysecretkey")
// 验证JWT
valid := validateJWT(token, "mysecretkey")
if valid {
fmt.Println("JWT is valid!")
} else {
fmt.Println("JWT is not valid.")
}
}
func createJWT(secretKey string) string {
// 创建一个令牌
token := jwt.New(jwt.SigningMethodHS256)
// 设置声明(Payload)
claims := token.Claims.(jwt.MapClaims)
claims["sub"] = "1234567890"
claims["name"] = "John Doe"
claims["iat"] = time.Now().Unix()
claims["exp"] = time.Now().Add(time.Hour * 24).Unix()
// 使用密钥签名令牌
tokenString, _ := token.SignedString([]byte(secretKey))
return tokenString
}
func validateJWT(tokenString string, secretKey string) bool {
// 解析JWT
token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
return []byte(secretKey), nil
})
if err != nil {
return false
}
// 验证签名
if _, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
return true
}
return false
}
JWT的优势在于:
- 无状态性:服务器不需要在数据库中存储会话信息,因为所有必要的信息都包含在JWT中。
- 可扩展性:可以自定义声明来携带额外的信息,适用于各种应用场景。
- 跨平台:由于JWT使用JSON作为载体,它在不同的编程语言和平台之间都可以很容易地解析和构建。
然而,需要注意的是:
- 安全性:虽然JWT能够保证数据完整性,但默认情况下只是签名,不包含加密。因此,不应该在JWT中存储敏感信息。
- 过期时间:JWT的载荷中通常会包含一个过期时间(exp),在验证时需要确保令牌在有效期内。
- 签名算法:选择适当的签名算法很重要,以确保安全性。常用的算法包括HMAC、RSA、ECDSA等。
总之,JWT是一种灵活且安全的标准,适用于许多不同的应用场景,如单点登录(SSO)、API身份验证等。通过合理地使用JWT,可以提高应用程序的安全性和可扩展性。