JWT是什么
jwt是Json Web Token简写,是一种基于json的开放标准RFC7519。其信息主要存放在客户端,主要用于在不同的服务终端之间安全地传输信息,常用于Web应用程序的身份验证和鉴权,如SSO登录
特点
设计紧凑且安全,分为三段构成,分别为header,payload,signature, 三部分均为Base64URL编码后的数据,通过点号连接。其中header和payload为json object base64URL编码后得到的字符串, signature是对header和payload的加密,用于验证jwt的合法性。jwt结构图如下:
组成
-
header
header只有两个字段,分别是:
- alg: 指定的加密算法,生成signature使用,如sha256, hmac等。
- typ: 说明jwt的类型,一般都是JWT
如下:
{ "alg": "HS256", "typ": "JWT" } -
payload
也被称为claim,是用来传递信息的地方,标准只有一些建议字段,并无强制要求必传的字段。用户可根据需求自行设计。如设置一个用户名和过期时间
{ "name": "test", "expire": 1726234962 }注: payload采用base64url编码,是可以被解码的,故在设计payload时不要传递敏感信息。
-
signature
签名是主要目的是为了保证jwt的完整性,其生成步骤主要是:
- 将header和payload进行base64url编码,然后使用点拼接,组成字符串 s1
- 使用header中指定的算法和后端存放的secret对 s1进行加密,得到加密传 s2
- 对最后的s2进行base64URL编码即可
比如使用使用HS256进行加密:
s1 = Base64UrlEncode(Header) + "." + Base64UrlEncode(payload) signature = Base64UrlEncode(HS256(s1, secret))如何校验jwt合法性:服务端获取到jwt串中的header和payload信息后,根据加密规则生成签名串并与jwt中的signature比对即可。
go代码演示
使用golang-jwt
-
下载 go get -u github.com/golang-jwt/jwt/v5
-
引用 import "github.com/golang-jwt/jwt/v5"
-
完整代码
package main import ( "crypto" "crypto/hmac" "encoding/base64" "encoding/json" "fmt" "github.com/golang-jwt/jwt/v5" ) func main() { secret := []byte("1223333") token, _ := createToken(secret) fmt.Println(token) validToken(token, secret) } // 加密 func createToken(secret []byte) (string, error) { token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{ "name": "john", "role": "admin", }) tokenString, err := token.SignedString(secret) return tokenString, err } // 解密 func validToken(tokenString string, secret []byte) { token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) { return secret, nil }) if err != nil { fmt.Println("err", err) return } fmt.Printf("valid:%v , payload:%v\n", token.Valid, token.Claims) }执行结果:
原生加密实现
func main() {
header := map[string]interface{}{
"typ": "JWT",
"alg": "HS256",
}
h, _ := json.Marshal(header)
hs := base64.RawURLEncoding.EncodeToString(h)
fmt.Println("header==>", hs)
claims := map[string]interface{}{
"name": "john",
"role": "admin",
}
c, _ := json.Marshal(claims)
cs := base64.RawURLEncoding.EncodeToString(c)
fmt.Println("payload==>", cs)
signingString := hs + "." + cs
hmacSampleSecret := []byte("1223333")
hasher := hmac.New(crypto.SHA256.New, hmacSampleSecret)
hasher.Write([]byte(signingString))
sign := hasher.Sum(nil)
ss := base64.RawURLEncoding.EncodeToString(sign)
fmt.Println("sign==>", ss)
}
输出结果
原生实现按照jwt定义进行实现,可以看出整个算法的实现过程比较简单。这也是jwt的好处之一,即实现简单。
总结
最后总结下jwt的优缺点以及适用场景。jwt适用sso登录,甚至应用之间的认证也可以使用jwt处理,总体而言jwt简单且灵活。
-
优点
- 易于使用: 传输方式无限制,header,url等均可。对比cookie不会存在跨域问题。
- 无状态:服务端不需要维护token信息,架构设计上较为简洁。
- 灵活:对payload无强制限制,可自由设置传输信息。
-
缺点
- 无法撤销,一般只要发出,有效期之前都是有效的