mozillazg / go-cos

腾讯云对象存储服务 COS(Cloud Object Storage) Go SDK(XML API)
https://godoc.org/github.com/mozillazg/go-cos
MIT License
88 stars 26 forks source link

请问有生成COS临时密钥的方法吗 #6

Closed MrSong0607 closed 5 years ago

MrSong0607 commented 6 years ago

移动端APP要上传文件到cos,直接存储secretkey 和secretid非常不安全,所以有另外一种方式,就是生成一个临时密钥 生成临时密钥的文档:https://cloud.tencent.com/document/product/436/9068 安卓用临时密钥上传文件:https://cloud.tencent.com/document/product/436/12159#.E7.94.9F.E6.88.90.E7.AD.BE.E5.90.8D

MrSong0607 commented 6 years ago

官网上面的示例只给出了python版,我自己写了个golang版,希望能整合进去

//AppTempSession .
func AppTempSession(secretID, secretKey string) (*QCloudTokenResult, error) {
    policy := `{"statement":[{"action":["name/cos:*"],"effect":"allow","resource":"*"}],"version":"2.0"}`
    baseURL, err := url.Parse("https://sts.api.qcloud.com/v2/index.php")
    if err != nil {
        return nil, err
    }

    param := make(map[string]string)
    param["name"] = "someone"
    param["policy"] = policy //base64.StdEncoding.EncodeToString([]byte(policy))
    param["durationSeconds"] = "7200"
    param["Timestamp"] = strconv.FormatInt(time.Now().Unix(), 10)

    rand.Seed(time.Now().Unix())
    param["Nonce"] = strconv.Itoa(rand.Int())
    param["SecretId"] = secretID
    param["Action"] = "GetFederationToken"

    sign := genSignature("get", baseURL.Host+baseURL.Path, secretKey, param)
    param["Signature"] = sign
    uParams := url.Values{}

    for k := range param {
        uParams.Add(k, param[k])
    }

    finalURL := baseURL.String() + "?" + uParams.Encode()

    resp, err := http.Get(finalURL)
    if err != nil {
        return nil, err
    }
    defer resp.Body.Close()

    bd, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        return nil, err
    }

    tk := &QCloudTokenResult{}
    return tk, JSONUnMarshal(string(bd), tk)
}

func genSignature(method, uri, secretkey string, param map[string]string) string {
    param["SignatureMethod"] = "HmacSHA1"

    var keys []string
    for k := range param {
        keys = append(keys, k)
    }
    sort.Strings(keys)

    str := strings.ToUpper(method) + uri + "?"
    for index := range keys {
        if index > 0 {
            str = str + "&"
        }
        str = str + keys[index] + "=" + param[keys[index]]
    }

    h := hmac.New(sha1.New, []byte(secretkey))
    if _, err := h.Write([]byte(str)); err != nil {
        return ""
    }

    return base64.StdEncoding.EncodeToString(h.Sum(nil))
}
solarhell commented 6 years ago

注意看commit https://github.com/mozillazg/go-cos/commit/f845dc5b530c2e764ed56367d6dc8d294f916020

mozillazg commented 6 years ago

@MrSong0607 感谢分享。还有一种方法是使用 @solarhell 提到的预签名 URL 来上传文件 https://github.com/mozillazg/go-cos/pull/5 你可以看看是否对你有帮助。

等我有空的时候会修改程序支持使用临时密钥,也欢迎提交 PR(倾向于只增加支持使用临时密钥计算签名的功能,获取临时密钥的操作由独立的包来实现,go-cos 不实现获取临时密钥的功能 )。

MrSong0607 commented 6 years ago

@solarhell @mozillazg 了解,感谢两位