github.com/GuanceCloud/cliutils@v1.1.21/network/http/aksk.go (about)

     1  // Unless explicitly stated otherwise all files in this repository are licensed
     2  // under the MIT License.
     3  // This product includes software developed at Guance Cloud (https://www.guance.com/).
     4  // Copyright 2021-present Guance, Inc.
     5  
     6  package http
     7  
     8  import (
     9  	"crypto/hmac"
    10  	"crypto/sha256"
    11  	"encoding/base64"
    12  	"fmt"
    13  	"net/http"
    14  	"sort"
    15  	"strings"
    16  )
    17  
    18  type SignOption struct {
    19  	AuthorizationType string
    20  	SignHeaders       []string // in order
    21  	SK                string
    22  	AK                string
    23  	Sign              string
    24  	SignStr           string
    25  }
    26  
    27  func DefaultSignOption(authType string, headers []string) *SignOption {
    28  	sort.Strings(headers)
    29  
    30  	return &SignOption{
    31  		AuthorizationType: authType,
    32  		SignHeaders:       headers,
    33  	}
    34  }
    35  
    36  func (o *SignOption) SignReq(r *http.Request) (string, error) {
    37  	signElems := []string{
    38  		r.Method,
    39  	}
    40  
    41  	sort.Strings(o.SignHeaders)
    42  
    43  	for _, v := range o.SignHeaders {
    44  		signElems = append(signElems, r.Header.Get(v))
    45  	}
    46  
    47  	o.SignStr = strings.Join(signElems, "\n")
    48  
    49  	h := hmac.New(sha256.New, []byte(o.SK))
    50  	if _, err := h.Write([]byte(o.SignStr)); err != nil {
    51  		return "", err
    52  	}
    53  
    54  	return base64.StdEncoding.EncodeToString(h.Sum(nil)), nil
    55  }
    56  
    57  func (o *SignOption) ParseAuth(r *http.Request) error {
    58  	authHeader := r.Header.Get(`Authorization`)
    59  
    60  	parts := strings.Split(authHeader, " ")
    61  	switch len(parts) {
    62  	case 2: //nolint:gomnd
    63  		if parts[0] != o.AuthorizationType {
    64  			return fmt.Errorf("unknown authorization type %s, expect %s", parts[0], o.AuthorizationType)
    65  		}
    66  
    67  		signParts := strings.Split(parts[1], `:`)
    68  		if len(signParts) != 2 { //nolint:gomnd
    69  			return fmt.Errorf("invalid Authorization header, expect format `type access_key:sign'")
    70  		}
    71  
    72  		o.AK = signParts[0]
    73  		o.Sign = signParts[1]
    74  		return nil
    75  
    76  	default:
    77  		return fmt.Errorf("invalid Authorization header, expect format `type access_key:sign'")
    78  	}
    79  }