JWT原理及Golang语言的简单应用

高能预警

正文

关于JWT

JWT 全名 Json Web Token,顾名思义:即 用于Web传输 加密的JSON对象过程时的令牌
一般是这样形状的:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdXRob3JpemVkIjp0cnVlLCJleHAiOjE2NDE5ODk4NDgsInVzZXJuYW1lIjoiYSJ9.zW11Cq8QNHTHJMUResrQeKVRTNLUlDymVsTPy2ororI

那我们如何从这串乱码中 得到我们想要的数据呢

分解JWT

我们通过观察这串乱码发现,其被“.”分割成了三部分,下面博主将分别解释这三段内容,请君继续阅读

JWT第一部分:Header

我们使用base64解密第一段:

func main() {
	decodeString, _ := base64.StdEncoding.DecodeString(
		"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9")
	fmt.Println(string(decodeString))
}

得到了这样的结果:

{"alg":"HS256","typ":"JWT"}
  • 我们通常把JWT的这部分称之为Header,也就是 头部typ字段表示令牌的类型,即这是一个“JWT”;
    和一个正在使用的签名算法,即HS256。当我们把这些信息组成一个JSON对象并使用base64加密算法加密后,即得到JWT的第一部分。

JWT第二部分:Payload

同样使用base64解密第二段,得到了这样的结果:

{"authorized":true,"exp":1641990483,"username":"a"}

实际上,这个JSON对象是我们自己定义的,代码如下:

func CreateJWT(username string, key string) (string, error) {
	c := jwt.MapClaims{}

	c["authorized"] = true
	c["username"] = username
	c["exp"] = time.Now().Add(600 * time.Second).Unix()

	t := jwt.NewWithClaims(jwt.SigningMethodHS256, c)

	token, err := t.SignedString([]byte(key))

	if err != nil {
		return "", err
	}

	return token, err
}
  • 我们通常把JWT第二部分称之为Payload,也就是 有效载荷,里面包含了我们自己定义的内容(通常为我们想要认证的字段),并进行base64加密。最终得到了JWT的第二部分。

  • 在这里,我们可以看到,首先创建了一个jwt.MapClaims{}类型的变量,实际上他就是map[string]interface{}的别名,我们可以直接塞入自定义数据。

// Claims type that uses the map[string]interface{} for JSON decoding
// This is the default claims type if you don't supply one
type MapClaims map[string]interface{}

到这里读者们可能会想到,既然jwt的内容这么“暴露”,我们该怎样使用它来建立信任呢?这就到了JWT最关键的第三部分——Signature了。

JWT第三部分:Signature

  • 这部分通常由JWT的header.payload部分,加上我们自己定义的密钥,通过头部声明的加密算法(第一部分的typ字段的值)加密后,得到了JWT的第三部分:签名

  • 把以上三部分放在一起,以“.”分隔的Base64-URL字符串,就是我们生成的完整的JWT了。
    可以在HTMLHTTP环境中轻松传递,同时与基于XML的标准(如 SAML)相比更加“紧实”。

小结

不论是我们自定义的密钥,还是JWT的签发过程,都是在服务端完成的,也就是说在我们保护好密钥的前提下,JWT是可以完成权限鉴定的。

附图

将JWT用于访问 API 或其他资源的过程
来自:jwt.io
感谢阅读。


版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/Liing0/article/details/122462776