将JWT有效负载转换回结构

时间:2019-08-22 14:01:38

标签: json go struct jwt

我无法将JWT有效负载转换回golang中的结构

我有两个相互通信的服务器,并具有JWT身份验证以加强安全性。

有效负载使用以下结构

type ResponseBody struct {
    Header       dto.MessageHeader       `json:"message_header"`
    OrderBodyParams dto.OrderBodyParams `json:"order_response"`
    Status              string                  `json:"status"`
    ErrorMessage        string                  `json:"errors"`
}

服务器A采用此结构-将其转换为字节日期并将其作为JWT有效负载发送

相关代码在下面

func request(secretKey string, path string, method string, requestParams interface{}, response interface{}) error {

    tr := &http.Transport{
        TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
    }
    client := &http.Client{
        Timeout:   time.Second * 15,
        Transport: tr,
    }

    //convert body into byte data
    requestBody, err := json.Marshal(requestParams)
    if err != nil {
        return err
    }

    tokenString, expirationTime, err := authentication.GenerateJWTAuthToken(secretKey, requestBody)
    if err != nil {
      return err
    }

    req, _ := http.NewRequest(method, path, bytes.NewBuffer([]byte(tokenString)))
    req.Header.Set("Content-Type", "application/json")
    req.AddCookie(&http.Cookie{
        Name:    "token",
        Value:   tokenString,
        Expires: expirationTime,
    })

    _, err = client.Do(req)

    if err != nil {
       return err
    }

    return nil
}

如您所见,我只是将主体转换为字节数据-并将其转换为JWT有效负载

GenerateJWTAuthToken函数如下所示

type Claims struct {
    Payload []byte `json:"payload"`
    jwt.StandardClaims
}


func GenerateJWTAuthToken(secretKey string, payload []byte) (string, time.Time, error) {
    var jwtKey = []byte(secretKey)

    // Set expiration to 5 minutes from now (Maybe lesser?)
    expirationTime := time.Now().Add(5 * time.Minute)
    // create the payload
    claims := &Claims{
        Payload: payload,
        StandardClaims: jwt.StandardClaims{
            ExpiresAt: expirationTime.Unix(),
        },
    }

    token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
    tokenString, err := token.SignedString(jwtKey)

    if err != nil {
        return "", time.Time{}, fmt.Errorf("Error generating JWT token : %+v", err)
    }
    return tokenString, expirationTime, nil
}

现在server B-接收数据并验证JWT,并将字节有效载荷转换回ResponseBody结构

func Postback(appState *appsetup.AppState) http.HandlerFunc {
    fn := func(w http.ResponseWriter, r *http.Request) {

        body, err := ioutil.ReadAll(r.Body)
        tokenString := string(body)
        if err != nil {
            w.WriteHeader(http.StatusUnauthorized)
            return
        }

        // Verify the JWT token send from server A and ensure its a valid request
        // If the token is invalid , dont proceed further
        token, payload, err := authentication.VerifyJWTToken(appState.SecretKey, tokenString)

        if err != nil {
            if err == jwt.ErrSignatureInvalid {
                w.WriteHeader(http.StatusUnauthorized)
                return
            }
            w.WriteHeader(http.StatusBadRequest)
            return
        }
        if !token.Valid {
            w.WriteHeader(http.StatusUnauthorized)
            return
        }


        requestData := ResponseBody{}
        err = binary.Read(bytes.NewReader(payload), binary.LittleEndian, &requestData)
        if err != nil {
            fmt.Printf("Couldnt convert payload body to struct : %+v ", err)
            return
        }
        return requestData
    }
    return http.HandlerFunc(fn)
}

VerifyJWTToken函数也非常简单(我希望如此)

func VerifyJWTToken(secretKey string, tokenString string) (*jwt.Token, []byte, error) {
    var jwtKey = []byte(secretKey)
    var payload []byte
    claims := &Claims{}

    token, err := jwt.ParseWithClaims(tokenString, claims, func(token *jwt.Token) (interface{}, error) {

        if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
            return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"])
        }

        return jwtKey, nil
    })

    if err != nil {
        return nil, payload, err
    }

    return token, claims.Payload, nil
}

但是我无法将payload转换回ResponseBody结构-

err = binary.Read(bytes.NewReader(bodyBuffer), binary.LittleEndian, &requestData)行似乎失败了

出现以下错误

msg":"Couldnt convert payload body to struct : binary.Read: invalid type *ResponseBody "

我有什么想念的吗?

1 个答案:

答案 0 :(得分:0)

您正在使用JSON封送您的结构:

requestBody, err := json.Marshal(requestParams)`

因此,您应该使用JSON解封来获取结构。但是,您正在使用binary.Read()来阅读它:

err = binary.Read(bytes.NewReader(payload), binary.LittleEndian, &requestData)

而是这样做:

err = json.Unmarshal(payload, &requestData)