Golang

关注公众号 jb51net

关闭
首页 > 脚本专栏 > Golang > Json web token(JWT)golang

Json web token(JWT)golang实现方式

作者:一条闲鱼_mytube

JWT由三部分组成:头部、载荷和签证,头部包含类型和加密算法;载荷包含声明;签证通过头部和载荷与密钥生成,JWT用于身份验证和信息交换,在Golang中,可以使用包https://github.com/tutengdihuang/jwt来实现JWT的生成、验证和解码

Json web token (JWT)

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.UQmqAUhUrpDVV2ST7mZKyLTomVfg7sYkEjmdDI5XF8Q

三部分构成

第一部头部(header)的作用​​​​​

声明类型

声明加密的算法 通常直接使用 HMAC SHA256

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

将头部进行base64加密

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9

第二部分载荷(payload)

载荷就是存放有效信息的地方:

标准中注册的声明

公共的声明

私有的声明

私有声明是提供者和消费者所共同定义的声明,一般不建议存放敏感信息,因为base64是对称解密的,意味着该部分信息可以归类为明文信息

{"sub": "1234567890","name": "John Doe","admin": true}然后将其进行base64加密,得到Jwt的第二部分
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9signature

第三部分签证(signature)

UQmqAUhUrpDVV2ST7mZKyLTomVfg7sYkEjmdDI5XF8Q

签名的目的

如何应用

一般是在请求头里加入Authorization,并加上Bearer标注

fetch('api/user/1', { headers: {'Authorization': 'Bearer ' + token }})服务端会验证token

如果验证通过,就会返回相应的资源

Golang 客户端实现

调用包 https://github.com/tutengdihuang/jwt

var jwtIns *JwtAuth

type JwtAuth struct {
	Lock      *sync.Mutex
	algorithm *jwt.Algorithm
	claimsMap map[string]*jwt.Claims //key: userID
}

func GetJwtAuth() *JwtAuth {
	if jwtIns == nil {
		once := sync.Once{}
		once.Do(
			func() {
				if jwtIns == nil {
					jwtIns = new(JwtAuth)
					jwtIns.Lock = new(sync.Mutex)
					jwtIns.claimsMap = make(map[string]*jwt.Claims)
					secret := config_center.GetViperConf().Sub("jwt").GetString("secret")
					algorithm := jwt.HmacSha256(secret)
					jwtIns.algorithm = &algorithm
				}
			})
	}
	return jwtIns
}
var jwtClaimUserKey = "username"
var jwtClaimUserIdKey = "id"

func (this *JwtAuth) GetToken(userName string, id int) (token string, err error) {
	claim := jwt.NewClaim()
	claim.Set(jwtClaimUserKey, userName)
	claim.Set(jwtClaimUserIdKey, strconv.Itoa(id))
	//claim.SetTime("expire", time.Now().Add(30*time.Minute))
	idstr := strconv.Itoa(id)
	this.Lock.Lock()
	defer this.Lock.Unlock()
	this.claimsMap[idstr] = claim
	token, err = this.algorithm.Encode(claim)
	return
}
func (this *JwtAuth) Validate(idstr, token string) bool {
	this.Lock.Lock()
	defer this.Lock.Unlock()
	if _, ok := this.claimsMap[idstr]; !ok {
		return false
	}
	if this.algorithm.Validate(token) != nil {
		return false
	}

	return true
}
func (this *JwtAuth) TokenDecode(token string) (string, int, error) {
	claim, err := this.algorithm.Decode(token)
	if err != nil {
		return "", 0, err
	}
	userName, err := claim.Get(jwtClaimUserKey)
	if err != nil {
		return "", 0, err
	}
	idStr, err := claim.Get(jwtClaimUserIdKey)
	if err != nil {
		return "", 0, err
	}
	id, _ := strconv.Atoi(idStr)
	return userName, id, nil
}
func (this *JwtAuth) TokenRemove(id string) {
	this.Lock.Lock()
	defer this.Lock.Unlock()
	delete(this.claimsMap, id)
}

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

您可能感兴趣的文章:
阅读全文