golang-simple JWT Posted on 2017-11-09 | In Golang 极简版本的JWT阅读具体RFC文档,获取大概内容https://tools.ietf.org/html/rfc7519 抽取最核心部分 jwt的组成 jwt的组成部分的核心算法 jwt的检验 尝试实现 此版本hardcode了 算法为HS256 package mainimport ( "crypto/hmac" "crypto/sha256" "encoding/base64" "encoding/json" "errors" "fmt" "log" "strings")// Token is the generated tokentype Token stringfunc main() { // type claims struct { // Iss string `json:"iss"` // Exp int64 `json:"exp"` // Sub string `json:",omitempty"` // Aud interface{} `json:",omitempty"` // Nbf int64 `json:",omitempty"` // Iat int64 `json:",omitempty"` // Jti string `json:",omitempty"` // } // 测试例子claims newClaims := map[string]interface{}{ "iss": "joe", "exp": 1300819380, "http://example.com/is_root1": true, } token, err := generateToken(nil, newClaims) if err != nil { log.Fatal(err) } payload, err := token.parser() if err != nil { log.Fatal(err) } for k, v := range payload { fmt.Printf("%s : %v %T \n", k, v, v) }}// 根据header 和 claims生成tokenfunc generateToken(header map[string]string, claims map[string]interface{}) (token Token, err error) { // 给header默认值如果是nil var joseHeader = map[string]string{ "typ": "JWT", "alg": "HS256", } if header == nil { header = joseHeader } b, err := json.Marshal(header) if err != nil { return } c, err := json.Marshal(claims) if err != nil { return } // 生成第三部分 hmacV := hmac.New(sha256.New, []byte(base64.URLEncoding.EncodeToString(b)+"."+base64.URLEncoding.EncodeToString(c))) // 第一部分.第二部分.第三部分 token = Token(base64.URLEncoding.EncodeToString(b) + "." + base64.URLEncoding.EncodeToString(c) + "." + base64.URLEncoding.EncodeToString(hmacV.Sum(nil))) return}// token 解析func (token Token) parser() (body map[string]interface{}, err error) { arr := strings.Split(string(token), ".") // 至少要有一个 . if len(arr) < 2 { err = errors.New("at least contain one '.'") return } // 验证是否是正常的url encode string,并且能够正常解析为json _, err = validate(arr[0]) if err != nil { return } payload, err := validate(arr[1]) if err != nil { return } // 根据前两个部分,能和第三部分签名匹配 hmacV := hmac.New(sha256.New, []byte(arr[0]+"."+arr[1])) if !hmac.Equal(hmacV.Sum(nil), []byte(arr[2])) { err = errors.New("hmac signature is not matched") return } // 把payload部分解析出来 err = json.Unmarshal(payload, &body) if err != nil { return } return}func validate(str string) (payload []byte, err error) { encodeStr, err := base64.URLEncoding.DecodeString(str) if err != nil { return } if !json.Valid(encodeStr) { err = errors.New("can not convert to json") return } return base64.URLEncoding.DecodeString(str)}