| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146 |
- package oss
- import (
- "bytes"
- "crypto/hmac"
- "crypto/sha1"
- "crypto/sha256"
- "encoding/base64"
- "fmt"
- "hash"
- "io"
- "net/http"
- "sort"
- "strings"
- )
- // headerSorter defines the key-value structure for storing the sorted data in signHeader.
- type headerSorter struct {
- Keys []string
- Vals []string
- }
- func (conn Conn) getAdditionalHeaderKeys(req *http.Request) []string {
- var additionalHeaderKeys []string
- for _, key := range conn.config.AdditionalHeaders {
- if _, ok := req.Header[key]; ok {
- additionalHeaderKeys = append(additionalHeaderKeys, key)
- }
- }
- return additionalHeaderKeys
- }
- // signHeader signs the header and sets it as the authorization header.
- func (conn Conn) signHeader(req *http.Request, canonicalizedResource string) {
- // Get the final authorization string
- authorizationStr := ""
- if conn.config.AuthVersion == AuthV2 {
- additionalHeaderKeys := conn.getAdditionalHeaderKeys(req)
- if len(additionalHeaderKeys) > 0 {
- authorizationFmt := "OSS2 AccessKeyId:%v,AdditionalHeaders:%v,Signature:%v"
- additionnalHeadersStr := strings.Join(additionalHeaderKeys, ";")
- authorizationStr = fmt.Sprintf(authorizationFmt, conn.config.AccessKeyID, additionnalHeadersStr, conn.getSignedStr(req, canonicalizedResource))
- } else {
- authorizationFmt := "OSS2 AccessKeyId:%v,Signature:%v"
- authorizationStr = fmt.Sprintf(authorizationFmt, conn.config.AccessKeyID, conn.getSignedStr(req, canonicalizedResource))
- }
- } else {
- authorizationStr = "OSS " + conn.config.AccessKeyID + ":" + conn.getSignedStr(req, canonicalizedResource)
- }
- // Give the parameter "Authorization" value
- req.Header.Set(HTTPHeaderAuthorization, authorizationStr)
- }
- func (conn Conn) getSignedStr(req *http.Request, canonicalizedResource string) string {
- // Find out the "x-oss-"'s address in header of the request
- ossHeadersMap := make(map[string]string)
- for k, v := range req.Header {
- if strings.HasPrefix(strings.ToLower(k), "x-oss-") {
- ossHeadersMap[strings.ToLower(k)] = v[0]
- }
- }
- hs := newHeaderSorter(ossHeadersMap)
- additionnalHeadersMap := make(map[string]string)
- additionalHeaders := ""
- if conn.config.AuthVersion == AuthV2 {
- additionalHeaderKeys := conn.getAdditionalHeaderKeys(req)
- for _, additionalHeaderKey := range additionalHeaderKeys {
- additionalHeaderValue := req.Header[additionalHeaderKey]
- hs.Keys = append(hs.Keys, strings.ToLower(additionalHeaderKey))
- hs.Vals = append(hs.Vals, additionalHeaderValue[0])
- additionnalHeadersMap[strings.ToLower(additionalHeaderKey)] = additionalHeaderValue[0]
- }
- ahs := newHeaderSorter(additionnalHeadersMap)
- ahs.Sort()
- for i := range ahs.Keys {
- additionalHeaders += ahs.Keys[i] + ":" + ahs.Vals[i] + ";"
- }
- }
- // Sort the headers by the ascending order
- hs.Sort()
- // Get the canonicalizedOSSHeaders
- canonicalizedOSSHeaders := ""
- for i := range hs.Keys {
- canonicalizedOSSHeaders += hs.Keys[i] + ":" + hs.Vals[i] + "\n"
- }
- // Give other parameters values
- // when sign URL, date is expires
- date := req.Header.Get(HTTPHeaderDate)
- contentType := req.Header.Get(HTTPHeaderContentType)
- contentMd5 := req.Header.Get(HTTPHeaderContentMD5)
- signStr := req.Method + "\n" + contentMd5 + "\n" + contentType + "\n" + date + "\n" + canonicalizedOSSHeaders + canonicalizedResource
- h := hmac.New(func() hash.Hash { return sha1.New() }, []byte(conn.config.AccessKeySecret))
- if conn.config.AuthVersion == AuthV2 {
- signStr = req.Method + "\n" + contentMd5 + "\n" + contentType + "\n" + date + "\n" + canonicalizedOSSHeaders + additionalHeaders + "\n" + canonicalizedResource
- h = hmac.New(func() hash.Hash { return sha256.New() }, []byte(conn.config.AccessKeySecret))
- }
- fmt.Printf("the value of signStr is %v", signStr)
- io.WriteString(h, signStr)
- signedStr := base64.StdEncoding.EncodeToString(h.Sum(nil))
- return signedStr
- }
- // newHeaderSorter is an additional function for function SignHeader.
- func newHeaderSorter(m map[string]string) *headerSorter {
- hs := &headerSorter{
- Keys: make([]string, 0, len(m)),
- Vals: make([]string, 0, len(m)),
- }
- for k, v := range m {
- hs.Keys = append(hs.Keys, k)
- hs.Vals = append(hs.Vals, v)
- }
- return hs
- }
- // Sort is an additional function for function SignHeader.
- func (hs *headerSorter) Sort() {
- sort.Sort(hs)
- }
- // Len is an additional function for function SignHeader.
- func (hs *headerSorter) Len() int {
- return len(hs.Vals)
- }
- // Less is an additional function for function SignHeader.
- func (hs *headerSorter) Less(i, j int) bool {
- return bytes.Compare([]byte(hs.Keys[i]), []byte(hs.Keys[j])) < 0
- }
- // Swap is an additional function for function SignHeader.
- func (hs *headerSorter) Swap(i, j int) {
- hs.Vals[i], hs.Vals[j] = hs.Vals[j], hs.Vals[i]
- hs.Keys[i], hs.Keys[j] = hs.Keys[j], hs.Keys[i]
- }
|