目的
- 實作 JWT 功能
紀錄
程式
jwt.go
package jwt
import (
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
"encoding/hex"
"encoding/json"
"fmt"
"strings"
"time"
)
var key = "CoryRightByYork!:P"
type header struct {
Alg string `json:"alg"`
Typ string `json:"typ"`
}
type payload struct {
Id string `json:"id"`
Timestamp int64 `json:"timestamp"`
}
func Generate(id string) string {
// 取得 header payload 結構體
header := getHeader()
payload := getPayload(id)
// 轉json格式
jsonTokenHeader, _ := json.Marshal(header)
jsonTokenPayload, _ := json.Marshal(payload)
// 加密
unsignedToken := structEncode(jsonTokenHeader) + "." + structEncode(jsonTokenPayload)
signature := encodeHS256(unsignedToken)
// 組合
jwtToken := unsignedToken + "." + signature
return jwtToken
}
func GetId(jwtToken string) string {
// 分割字串取得 payload 部分
split := strings.Split(jwtToken, ".")
payloadByte := structDecode(split[1])
// 宣告空 payload
payload := payload{}
// 解析 payload
if err := json.Unmarshal(payloadByte, &payload); err != nil {
fmt.Println(`failed payload Decode`, err)
}
return payload.Id
}
func getHeader() *header {
return &header{
Alg: "HS256",
Typ: "JWT",
}
}
func getPayload(id string) *payload {
return &payload{
Id: id,
Timestamp: time.Now().Unix(),
}
}
func structEncode(s []byte) string {
return base64.RawURLEncoding.EncodeToString(s)
}
func structDecode(str string) []byte {
b, err := base64.RawURLEncoding.DecodeString(str)
if err != nil {
fmt.Println(`failed base64 Decode`, err)
}
return b
}
func encodeHS256(u string) string {
// new 一個 HMAC 結構體使用 jwt 的 key
h := hmac.New(sha256.New, []byte(key))
// 寫入資料
h.Write([]byte(u))
// Get result and encode as hexadecimal string
return hex.EncodeToString(h.Sum(nil))
}
func DecodeHS256(u string) string {
return "TO DO"
}
使用
token := jwt.Generate(user)
useId := jwt.GetId(token)