package datacenter_client import ( "bytes" "crypto/md5" "encoding/hex" "encoding/json" "fmt" "io/ioutil" "metawant.greentech.com.cn/gaoyagang/gt-common/httplib" "net/http" "net/url" "sort" "time" ) type DcApiClient struct { ServerIp string AppName string AppSecret string } const ( S2_MIN_LENGTH = 2048 S2_HEAD_LENGTH = 200 S2_TAIL_LENGTH = 200 ) func CreateDcApiClient(ip, appName, appSecret string) *DcApiClient { return &DcApiClient{ ServerIp: ip, AppName: appName, AppSecret: appSecret, } } func (d *DcApiClient) RequestMiddleProcess(h *httplib.HTTPRequest, projectId string) ([]byte, error) { //h.Header("X-Forwarded-For", "127.0.0.1") h.Header("APP-NAME", d.AppName) ts := time.Now().Unix() h.Param("project_id", projectId) h.Param("ts", fmt.Sprintf("%d", ts)) sign := d.CreateSign(h) h.Param("sign", sign) return h.Bytes() } func (d *DcApiClient)CreateSign(h *httplib.HTTPRequest) string { s2, err := parseBody(h) if err != nil { fmt.Println("parseBody Error: ", err.Error()) } contentLength := h.GetRequest().ContentLength if contentLength > S2_MIN_LENGTH { h.Param("sign_flag", "1") s2 = cutS2(s2) } else { s2, _ = sortS2(s2) } s3 := contentLength s1 := parseQuery(h) m := md5.New() m.Write([]byte(fmt.Sprintf("%s%s%d%s", s1, s2, s3, d.AppSecret))) md5Str := hex.EncodeToString(m.Sum(nil)) //fmt.Println("s1", s1) //fmt.Println("s2", s2) //fmt.Println("s3", s3) //fmt.Println("md5", md5Str) return md5Str } func cutS2(s2 string) string { s2l := len(s2) //if s2l <= S2_MIN_LENGTH { // return s2 //} return fmt.Sprintf("%s%s", s2[:S2_HEAD_LENGTH], s2[s2l-S2_TAIL_LENGTH:]) } func sortS2(s2 string) (string, error) { var mi map[string]interface{} if err := json.Unmarshal([]byte(s2), &mi); err != nil { return "", err } smi := SortMapByKey(mi) if bs, err := json.Marshal(smi); err != nil { return "", err } else { return string(bs), nil } } func parseBody(r *httplib.HTTPRequest) (s2 string, err error) { if r.GetRequest().Method == http.MethodGet { return "", nil } body := r.GetRequest().Body cnt, _ := ioutil.ReadAll(body) r.GetRequest().Body = ioutil.NopCloser(bytes.NewReader(cnt)) return string(cnt), nil } func parseQuery(r *httplib.HTTPRequest) string { params := r.GetQueryParam() delete(params, "sign") val := url.Values{} for k, v := range params { for index, s := range v { if index == 0 { val.Set(k, s) } else { val.Add(k, s) } } } return val.Encode() } // SortMapByKey 对 map[string]interface{} 按照键进行排序 func SortMapByKey(m map[string]interface{}) map[string]interface{} { // 创建一个 map[string]int,用于记录键的索引 indexMap := make(map[string]int) for k := range m { indexMap[k] = len(indexMap) } // 对键进行排序 keys := make([]string, 0, len(indexMap)) for k := range indexMap { keys = append(keys, k) } sort.Strings(keys) // 创建排序后的 map[string]interface{} sortedMap := make(map[string]interface{}) for _, k := range keys { sortedMap[k] = m[k] } return sortedMap }