Code is cheap, talk is expensive
JWT
is short for JSON Web Token
JSON Web Token (JWT) is an open standard (RFC 7519) that defines a compact and self-contained way for securely transmitting information between parties as a JSON object. This information can be verified and trusted because it is digitally signed. JWTs can be signed using a secret (with the HMAC algorithm) or a public/private key pair using RSA or ECDSA.
可见,JWT
主要是用来在不同组间安全传输 JSON 信息。
自我包含,可被信任。
三部分组成,由.
分割
最终的结果类似于:xxxxx.yyyyy.zzzzz
{ "alg": "HS256", "typ": "JWT" }
由加密算法和 JWT 标识组成
这里就是你要传输的json
结构体了,不建议传输私密信息,JWT 不是干这个的。
根据上面两个内容来生产一个签名,签名用来验证消息发送者的真伪。
HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret);
上面的就是签名,其中secret
是私钥,需要自己保管好。
最后讲上面三个内容按照先进行base64
之后再按照aa.bb.cc
组合在一起就是一个 JWT 了,看上去还是挺简单的。
需要记住的是,payload
只是经过简单base64
因此不能传输私密内容。
github
上面的 jwt 包,一般都是使用map[string]interface{}
来装载任意json
结构体。
在进行payload
这一步的时候,会用到json.Marshal()
方法来产生json
字符串。
由于使用到了map
,总所周知,map
的遍历是无序的,因此同一个json
结构,可能会参数不同的JWT
出来,如果服务器对此收到的payload
字段位置没有要求,这样做是没有问题。但是如果,有要求的话,就会产生问题。
为此,解决方案是放弃map
方案,使用struct
结构体,这样的不便之处就是,必须为每一个json
结构定义一个struct
,按照需要的字段定义即可,这样序列化结构体的时候就可以保留字段的信息。
虽然会有点不方便,不过确实是一个很不错的解决方案。
jwt
实现package jwt import ( "crypto/hmac" "crypto/sha256" "encoding/base64" "encoding/json" ) type HS256 struct { Claim interface{} Key string } type header struct { Alg string `json:"alg"` Typ string `json:"typ"` } func (h HS256) header() *header { return &header{ Typ: "JWT", Alg: "HS256", } } func (h HS256) Encode() (string, error) { header, _ := json.Marshal(h.header()) jsonHeader := base64.RawURLEncoding.EncodeToString(header) claim, err := json.Marshal(h.Claim) if err != nil { return "", err } jsonClaim := base64.RawURLEncoding.EncodeToString(claim) unsigned := jsonHeader + "." + jsonClaim hh := hmac.New(sha256.New, []byte(h.Key)) if _, err := hh.Write([]byte(unsigned)); err != nil { return "", err } signed := base64.RawURLEncoding.EncodeToString(hh.Sum(nil)) return jsonHeader + "." + jsonClaim + "." + signed, nil }
使用示例
func main(){ j := jwt.HS256{ Claim: struct { P string `json:"p"` T int64 `json:"t"` B string `json:"b"` W int `json:"w"` Iat int64 `json:"iat"` }{ P: "11", T: 1583075639000, B: "12054", W: 1000, Iat: 1583075639, }, Key: jwtKey, } fmt.Println(j.Encode()) }