1package oss 2 3import ( 4 "bytes" 5 "crypto/hmac" 6 "crypto/sha1" 7 "encoding/base64" 8 "hash" 9 "io" 10 "net/http" 11 "sort" 12 "strings" 13) 14 15// headerSorter defines the key-value structure for storing the sorted data in signHeader. 16type headerSorter struct { 17 Keys []string 18 Vals []string 19} 20 21// signHeader signs the header and sets it as the authorization header. 22func (conn Conn) signHeader(req *http.Request, canonicalizedResource string) { 23 // Get the final authorization string 24 authorizationStr := "OSS " + conn.config.AccessKeyID + ":" + conn.getSignedStr(req, canonicalizedResource) 25 26 // Give the parameter "Authorization" value 27 req.Header.Set(HTTPHeaderAuthorization, authorizationStr) 28} 29 30func (conn Conn) getSignedStr(req *http.Request, canonicalizedResource string) string { 31 // Find out the "x-oss-"'s address in header of the request 32 temp := make(map[string]string) 33 34 for k, v := range req.Header { 35 if strings.HasPrefix(strings.ToLower(k), "x-oss-") { 36 temp[strings.ToLower(k)] = v[0] 37 } 38 } 39 hs := newHeaderSorter(temp) 40 41 // Sort the temp by the ascending order 42 hs.Sort() 43 44 // Get the canonicalizedOSSHeaders 45 canonicalizedOSSHeaders := "" 46 for i := range hs.Keys { 47 canonicalizedOSSHeaders += hs.Keys[i] + ":" + hs.Vals[i] + "\n" 48 } 49 50 // Give other parameters values 51 // when sign URL, date is expires 52 date := req.Header.Get(HTTPHeaderDate) 53 contentType := req.Header.Get(HTTPHeaderContentType) 54 contentMd5 := req.Header.Get(HTTPHeaderContentMD5) 55 56 signStr := req.Method + "\n" + contentMd5 + "\n" + contentType + "\n" + date + "\n" + canonicalizedOSSHeaders + canonicalizedResource 57 h := hmac.New(func() hash.Hash { return sha1.New() }, []byte(conn.config.AccessKeySecret)) 58 io.WriteString(h, signStr) 59 signedStr := base64.StdEncoding.EncodeToString(h.Sum(nil)) 60 61 return signedStr 62} 63 64// newHeaderSorter is an additional function for function SignHeader. 65func newHeaderSorter(m map[string]string) *headerSorter { 66 hs := &headerSorter{ 67 Keys: make([]string, 0, len(m)), 68 Vals: make([]string, 0, len(m)), 69 } 70 71 for k, v := range m { 72 hs.Keys = append(hs.Keys, k) 73 hs.Vals = append(hs.Vals, v) 74 } 75 return hs 76} 77 78// Sort is an additional function for function SignHeader. 79func (hs *headerSorter) Sort() { 80 sort.Sort(hs) 81} 82 83// Len is an additional function for function SignHeader. 84func (hs *headerSorter) Len() int { 85 return len(hs.Vals) 86} 87 88// Less is an additional function for function SignHeader. 89func (hs *headerSorter) Less(i, j int) bool { 90 return bytes.Compare([]byte(hs.Keys[i]), []byte(hs.Keys[j])) < 0 91} 92 93// Swap is an additional function for function SignHeader. 94func (hs *headerSorter) Swap(i, j int) { 95 hs.Vals[i], hs.Vals[j] = hs.Vals[j], hs.Vals[i] 96 hs.Keys[i], hs.Keys[j] = hs.Keys[j], hs.Keys[i] 97} 98