Categorygithub.com/ihezebin/jwt
modulepackage
1.0.0
Repository: https://github.com/ihezebin/jwt.git
Documentation: pkg.go.dev

# README

jwt

A Golang Implementation of JSON Web Token

基于官方规范的实现,

使用

安装

go get github.com/ihezebin/jwt

生成 Token

const secret = "secret"

func TestGenerateToken(t *testing.T) {
token := Default(WithOwner("hezebin"), WithExternalKV("key", "value"), WithExpire(time.Second*30))
	signed, err := token.Signed(secret)
	if err != nil {
		t.Fatal(err)
	}
	t.Log(signed)
	t.Log(token.Faked())
	t.Log(token.Expired())
	t.Logf("%+v", token.Payload())
}

校验解析 Token

const tokenStr = "eyJlbmNvZGUiOiJiYXNlNjRyYXd1cmwiLCJ0eXAiOiJqd3QiLCJhbGciOiJIU0EyNTYifQ.eyJpc3N1ZXIiOiJnaXRodWIuY29tL2loZXplYmluL2p3dCIsIm93bmVyIjoiaGV6ZWJpbiIsInB1cnBvc2UiOiJhdXRoZW50aWNhdGlvbiIsImlzc3VlZF9hdCI6IjIwMjQtMDQtMDdUMTQ6MTk6MTYuNzkxNzE5KzA4OjAwIiwiZXhwaXJlIjozMDAwMDAwMDAwMCwiZXh0ZXJuYWwiOnsia2V5IjoidmFsdWUifX0.gGzRAc-IbrkaBqM_UxXtxxPMye_-MVzRHZt7sg9lTAA"
const fakeStr = "eyJlbmNvZGUiOiJiYXNlNjRyYXd1cmwiLCJ0eXAiOiJqd3QiLCJhbGciOiJIU0EyNTYifQ." +
	"eyJpc3N1ZXIiOiJnaXRodWIuY29tL2loZXplYmluL2p3dCIsIm93bmVyIjoiaGV6ZWJpbiIsInB1cnBvc2UiOiJhdXRoZW50aWNhdGlvbiIsImlzc3VlZF9hdCI6IjIwMjQtMDQtMDdUMTQ6MDU6NTcuNzk3MTgxKzA4OjAwIiwiZXhwaXJlIjozMDAwMDAwMDAwMCwiZXh0ZXJuYWwiOnsia2V5IjoidmFsdWUifX0.KKVwvFwaG8K_KfxHeJVjiAjqA83E0WLiCBLH4FsD3591"

func TestParseToken(t *testing.T) {
	token, err := Parse(tokenStr, secret)
	if err != nil {
		t.Fatal(err)
	}

	t.Log(token.Faked())
	t.Log(token.Expired())
	t.Logf("%+v", token.Payload())
}
func TestParseTokenFake(t *testing.T) {
	token, err := Parse(fakeStr, secret)
	if err != nil {
		t.Fatal(err)
	}

	t.Log(token.Faked())
	t.Log(token.Expired())
	t.Logf("%+v", token.Payload())
}

自定义加密算法

实现自定义加密算法后需要注册统一管理,以便解析 token 时从 header 中读取对应的算法

import (
	"crypto/hmac"
	"crypto/sha256"
)

type hsa256 struct {
}

func HSA256() Algorithm {
	return &hsa256{}
}

func (alg *hsa256) Name() string {
	return "HSA256"
}

func (alg *hsa256) Encrypt(signing, secret string) ([]byte, error) {
	h := hmac.New(sha256.New, []byte(secret))
	_, err := h.Write([]byte(signing))
	if err != nil {
		return nil, err
	}
	return h.Sum(nil), nil
}

func init() {
	RegisterAlgorithm(HSA256())
}

JWT 原理

1.简述

JWT(JSON Web Token)是一种开放标准(RFC 7519),用于在各方之间安全地传输信息作为 JSON 对象。JWT 可以在用户和服务器之间传递安全可靠的信息,因为它使用数字签名(在最简单的情况下也可以是加密)来验证信息的可靠性。下面是 JWT 协议的详细讲解:

2.结构:

JWT 由三部分组成,分别是 Header、Payload 和 Signature。这三部分通常使用 Base64 编码后连接在一起,中间用英文句点(.)分隔。

  • Header:包含了 Token 类型(即 JWT)、所使用的加密算法等信息。通常是一个 JSON 对象。
  • Payload:即 Token 的主体内容,包含了要传输的信息,也是一个 JSON 对象。
  • Signature:用于验证 Token 真实性的签名部分,由 Header 和 Payload 使用指定的算法加密后得到的。

因此,jwt 通常的字符结构为:xxxxx.yyyyy.zzzzz

2.1 Header

Header 通常由两部分组成:令牌的类型(即 JWT)和正在使用的签名算法,例如 HMAC SHA256 或 RSA。例如:

{
  "alg": "HS256",
  "typ": "JWT"
}

此 JSON 被 Base64Url 编码以形成JWT的第一部分。

2.2 Payload

Payload 包含 Claims; Claims 是有关实体(通常是用户)和其他数据的声明,不放用户敏感的信息,如密码。

2.2.1 Claims

Claims 是 JWT 官方规范中定义的名词,用于描述 Token 中包含的声明信息。在 JWT 规范中,Token 是由 Header、Payload 和 Signature 组成的,而 Payload 中包含了 Claims,用于携带各种声明信息,比如用户ID、过期时间、权限等等。这些声明信息由 Token 的颁发者自行定义和添加,以满足具体的需求。

Claims 同样使用Base64编码,分为共有声明和私有声明:

  • 公有声明: JWT提供了内置关键字用于描述常见的问题,此部分均为可选项,用户根据自己的需求,按需添加key,常见的公共声明如下:
{   'exp':xxx,  # Expiration Time,此Token的过期时间的时间戳
    'iss':xxx,  #(Issuer)指明此token的签发者
    'iat':xxx,  # Issued at 指明此创建时间内的时间戳
    'aud':xxx,  # Audience 指明此Token签发面向群体
}

特殊说明: 若 encode 得时候 payload 中添加了 exp 字段;则 exp 字段的值需为 "当前时间戳+此token的有效期时间",例如希望 token 300秒后过期。

{"exp":time.time()+300}在执行 decode 时,若检查到 exp 字段,且 token 过期,则抛出 jwt.ExpiredSignatureError

  • 私有声明: 用户可根据自己的业务需求,添加自定义的key,如下:
{"username": "hezebin"}

公有声明和私有声明均在同一个字典中,转成 json 串并用 base64 编码

2.3 Signature

根据 header 中的 alg 确定具体算法,以下用HS256为例: HS256(自定义的key,base64后的header + '.'+base64后的payload)

HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret);

最后再将得到的结果进行 base64 编码。

2.3.1 签名目的

签名的过程实际上是对头部以及负载内容进行签名,防止内容被窜改。如果有人对头部以及负载的内容解码之后进行修改, 再进行编码,最后加上之前的签名组合形成新的JWT的话,那么服务器端会判断出新的头部和负载形成的签名和JWT附带上的签名是不一样的。 如果要对新的头部和负载进行签名,在不知道服务器加密时用的密钥的话,得出来的签名也是不一样的。

2.3.2 信息安全

Base64是一种编码,是可逆的,适合传递一些非敏感信息。请注意,对于签名令牌,此信息虽然受到篡改保护,但任何人都可以读取。不要将机密信息放在 JWT 的有效负载或标头元素中,除非它已加密。

3.生成过程:

  • 选择合适的加密算法(如 HMAC、RSA 等)和密钥。
  • 将要传输的信息写入 Payload。
  • 使用选定的加密算法和密钥对 Header 和 Payload 进行加密,生成 Signature。
  • 将 Header、Payload 和 Signature 连接起来,生成 JWT。

4.验证过程:

  • 接收到 JWT 后,将其按照同样的方式拆分成 Header、Payload 和 Signature。
  • 使用相同的算法和密钥对 Header 和 Payload 进行加密,得到一个新的 Signature。
  • 将新生成的 Signature 与接收到的 Signature 进行比较,如果相同,则验证通过,否则认为 Token 无效。

5.使用场景:

认证:用于验证用户身份,比如用户登录后颁发一个包含用户信息的 JWT。 授权:在用户身份验证通过后,可以根据用户权限颁发特定权限的 JWT,用于访问特定资源。

# Packages

No description provided by the author

# Functions

No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author

# Structs

No description provided by the author

# Type aliases

No description provided by the author
No description provided by the author