简介
Go SDK 提供获取请求预签名 URL 接口,详细操作请查看本文示例。
注意事项
2024年1月1日后创建的桶 不支持使用默认域名在浏览器预览文件,建议您配置自定义域名,详情请参见 存储桶切换自定义域名。
建议用户使用临时密钥生成预签名,通过临时授权的方式进一步提高预签名上传、下载等请求的安全性。申请临时密钥时,请遵循 最小权限指引原则,防止泄露目标存储桶或对象之外的资源。
如果您一定要使用永久密钥来生成预签名,建议永久密钥的权限范围仅限于上传或下载操作,以规避风险。
相关示例
功能名称 | 描述 | 示例代码 |
生成预签名 URL | 对象存储(Cloud Object Storage,COS)支持使用预签名 URL 进行对象的上传、下载,原理是将签名嵌入 URL 生成签名链接。 |
获取请求预签名 URL
方法原型
func (s *ObjectService) GetPresignedURL(ctx context.Context, httpMethod, key, ak, sk string, expired time.Duration, opt interface{}, signHost ...bool) (*url.URL, error)
参数说明
type PresignedURLOptions struct {Query *url.ValuesHeader *http.Header}
参数名称 | 类型 | 描述 |
httpMethod | string | HTTP 请求方法 |
key | string | |
ak | string | SecretId |
sk | string | SecretKey |
expired | time.Duration | 签名有效时长 |
opt | interface{} | 扩展项,建议填写 *PresignedURLOptions 类型的参数。可填nil |
PresignedURLOptions | struct | 指定签入的请求参数和请求头部 |
Query | struct | 签名中要签入的请求参数 |
Header | struct | 签名中要签入的请求头部 |
signHost | bool | 可选参数,默认为true,获取签名时是否签入Header Host;您也可以选择不签入 Header Host,但可能导致请求失败或安全漏洞 |
返回结果说明
该方法返回值为预签名的下载 URL。
使用案例:永久密钥预签名上传请求
package mainimport ("context""github.com/tencentyun/cos-go-sdk-v5""net/http""net/url""os""strings""time")func main() {// 存储桶名称,由 bucketname-appid 组成,appid 必须填入,可以在 COS 控制台查看存储桶名称。 https://console.cloud.tencent.com/cos5/bucket// 替换为用户的 region,存储桶 region 可以在 COS 控制台“存储桶概览”查看 https://console.cloud.tencent.com/ ,关于地域的详情见 https://cloud.tencent.com/document/product/436/6224 。u, _ := url.Parse("https://examplebucket-1250000000.cos.ap-guangzhou.myqcloud.com")b := &cos.BaseURL{BucketURL: u}client := cos.NewClient(b, &http.Client{Transport: &cos.AuthorizationTransport{// 通过环境变量获取密钥// 环境变量 SECRETID 表示用户的 SecretId,登录访问管理控制台查看密钥,https://console.cloud.tencent.com/cam/capiSecretID: os.Getenv("SECRETID"), // 用户的 SecretId,建议使用子账号密钥,授权遵循最小权限指引,降低使用风险。子账号密钥获取可参见 https://cloud.tencent.com/document/product/598/37140// 环境变量 SECRETKEY 表示用户的 SecretKey,登录访问管理控制台查看密钥,https://console.cloud.tencent.com/cam/capiSecretKey: os.Getenv("SECRETKEY"), // 用户的 SecretKey,建议使用子账号密钥,授权遵循最小权限指引,降低使用风险。子账号密钥获取可参见 https://cloud.tencent.com/document/product/598/37140},})// 通过环境变量获取密钥// 环境变量 SECRETID 表示用户的 SecretId,登录访问管理控制台查看密钥,https://console.cloud.tencent.com/cam/capiak := os.Getenv("SECRETID") // 用户的 SecretId,建议使用子账号密钥,授权遵循最小权限指引,降低使用风险。子账号密钥获取可参见 https://cloud.tencent.com/document/product/598/37140// 环境变量 SECRETKEY 表示用户的 SecretKey,登录访问管理控制台查看密钥,https://console.cloud.tencent.com/cam/capisk := os.Getenv("SECRETKEY") // 用户的 SecretKey,建议使用子账号密钥,授权遵循最小权限指引,降低使用风险。子账号密钥获取可参见 https://cloud.tencent.com/document/product/598/37140name := "exampleobject"ctx := context.Background()f := strings.NewReader("test")// 1. 通过普通方式上传对象_, err := client.Object.Put(ctx, name, f, nil)if err != nil {panic(err)}// 获取预签名 URLpresignedURL, err := client.Object.GetPresignedURL(ctx, http.MethodPut, name, ak, sk, time.Hour, nil)if err != nil {panic(err)}// 2. 通过预签名方式上传对象data := "test upload with presignedURL"f = strings.NewReader(data)req, err := http.NewRequest(http.MethodPut, presignedURL.String(), f)if err != nil {panic(err)}// 用户可自行设置请求头部req.Header.Set("Content-Type", "text/html")_, err = http.DefaultClient.Do(req)if err != nil {panic(err)}}
使用案例:永久密钥预签名下载请求
package mainimport ("bytes""context""errors""github.com/tencentyun/cos-go-sdk-v5""io""net/http""net/url""os""time")func main() {// 存储桶名称,由 bucketname-appid 组成,appid 必须填入,可以在 COS 控制台查看存储桶名称。 https://console.cloud.tencent.com/cos5/bucket// 替换为用户的 region,存储桶 region 可以在 COS 控制台“存储桶概览”查看 https://console.cloud.tencent.com/ ,关于地域的详情见 https://cloud.tencent.com/document/product/436/6224 。u, _ := url.Parse("https://examplebucket-1250000000.cos.ap-guangzhou.myqcloud.com")b := &cos.BaseURL{BucketURL: u}client := cos.NewClient(b, &http.Client{Transport: &cos.AuthorizationTransport{// 通过环境变量获取密钥// 环境变量 SECRETID 表示用户的 SecretId,登录访问管理控制台查看密钥,https://console.cloud.tencent.com/cam/capiSecretID: os.Getenv("SECRETID"), // 用户的 SecretId,建议使用子账号密钥,授权遵循最小权限指引,降低使用风险。子账号密钥获取可参见 https://cloud.tencent.com/document/product/598/37140// 环境变量 SECRETKEY 表示用户的 SecretKey,登录访问管理控制台查看密钥,https://console.cloud.tencent.com/cam/capiSecretKey: os.Getenv("SECRETKEY"), // 用户的 SecretKey,建议使用子账号密钥,授权遵循最小权限指引,降低使用风险。子账号密钥获取可参见 https://cloud.tencent.com/document/product/598/37140},})// 通过环境变量获取密钥// 环境变量 SECRETID 表示用户的 SecretId,登录访问管理控制台查看密钥,https://console.cloud.tencent.com/cam/capiak := os.Getenv("SECRETID") // 用户的 SecretId,建议使用子账号密钥,授权遵循最小权限指引,降低使用风险。子账号密钥获取可参见 https://cloud.tencent.com/document/product/598/37140// 环境变量 SECRETKEY 表示用户的 SecretKey,登录访问管理控制台查看密钥,https://console.cloud.tencent.com/cam/capisk := os.Getenv("SECRETKEY") // 用户的 SecretKey,建议使用子账号密钥,授权遵循最小权限指引,降低使用风险。子账号密钥获取可参见 https://cloud.tencent.com/document/product/598/37140name := "exampleobject"ctx := context.Background()// 1. 通过普通方式下载对象resp, err := client.Object.Get(ctx, name, nil)if err != nil {panic(err)}bs, _ := io.ReadAll(resp.Body)resp.Body.Close()// 获取预签名 URLpresignedURL, err := client.Object.GetPresignedURL(ctx, http.MethodGet, name, ak, sk, time.Hour, nil)if err != nil {panic(err)}// 2. 通过预签名 URL下载对象resp2, err := http.Get(presignedURL.String())if err != nil {panic(err)}bs2, _ := io.ReadAll(resp2.Body)resp2.Body.Close()if bytes.Compare(bs2, bs) != 0 {panic(errors.New("content is not consistent"))}}
使用案例:临时密钥预签名上传请求
package mainimport ("context""fmt""github.com/tencentyun/cos-go-sdk-v5""net/http""net/url""os""time""strings")// 通过 tag 的方式,用户可以将请求参数或者请求头部放进签名中。type URLToken struct {SessionToken string `url:"x-cos-security-token,omitempty" header:"-"`}func main() {// 请替换成您的临时密钥tak := os.Getenv("SECRETID") // 用户的临时密钥SecretId,授权遵循最小权限指引,降低使用风险。临时密钥获取可参见 https://cloud.tencent.com/document/product/436/14048tsk := os.Getenv("SECRETKEY") // 用户的临时密钥SecretKey,授权遵循最小权限指引,降低使用风险。临时密钥获取可参见 https://cloud.tencent.com/document/product/436/14048token := &URLToken{SessionToken: "<token>",}u, _ := url.Parse("https://examplebucket-1250000000.cos.ap-guangzhou.myqcloud.com")b := &cos.BaseURL{BucketURL: u}c := cos.NewClient(b, &http.Client{})name := "exampleobject"ctx := context.Background()// 方法1 通过 PresignedURLOptions 设置 x-cos-security-token// PresignedURLOptions 提供用户添加请求参数和请求头部opt := &cos.PresignedURLOptions{Query: &url.Values{},Header: &http.Header{},}opt.Query.Add("x-cos-security-token", "<token>")// 获取预签名presignedURL, err := c.Object.GetPresignedURL(ctx, http.MethodPut, name, tak, tsk, time.Hour, opt)if err != nil {fmt.Printf("Error: %v\\n", err)return}// 通过预签名方式上传对象data := "test upload with presignedURL"f := strings.NewReader(data)req, err := http.NewRequest(http.MethodPut, presignedURL.String(), f)if err != nil {fmt.Printf("Error: %v\\n", err)}_, err = http.DefaultClient.Do(req)if err != nil {fmt.Printf("Error: %v\\n", err)}// 方法2 通过 tag 设置 x-cos-security-token// 获取预签名presignedURL, err = c.Object.GetPresignedURL(ctx, http.MethodPut, name, tak, tsk, time.Hour, token)if err != nil {fmt.Printf("Error: %v\\n", err)return}f = strings.NewReader(data)req, err = http.NewRequest(http.MethodPut, presignedURL.String(), f)if err != nil {fmt.Printf("Error: %v\\n", err)}_, err = http.DefaultClient.Do(req)if err != nil {fmt.Printf("Error: %v\\n", err)}}
使用案例:临时密钥预签名下载请求
package mainimport ("context""fmt""github.com/tencentyun/cos-go-sdk-v5""net/http""net/url""os""time")// 通过 tag 的方式,用户可以将请求参数或者请求头部放进签名中。type URLToken struct {SessionToken string `url:"x-cos-security-token,omitempty" header:"-"`}func main() {// 替换成您的临时密钥tak := os.Getenv("SECRETID") // 用户的临时密钥SecretId,授权遵循最小权限指引,降低使用风险。临时密钥获取可参见 https://cloud.tencent.com/document/product/436/14048tsk := os.Getenv("SECRETKEY") // 用户的临时密钥SecretKey,授权遵循最小权限指引,降低使用风险。临时密钥获取可参见 https://cloud.tencent.com/document/product/436/14048token := &URLToken{SessionToken: "<token>",}u, _ := url.Parse("https://examplebucket-1250000000.cos.ap-guangzhou.myqcloud.com")b := &cos.BaseURL{BucketURL: u}c := cos.NewClient(b, &http.Client{})name := "exampleobject"ctx := context.Background()// 方法1 通过 PresignedURLOptions 设置 x-cos-security-token// PresignedURLOptions 提供用户添加请求参数和请求头部opt := &cos.PresignedURLOptions{Query: &url.Values{},Header: &http.Header{},}opt.Query.Add("x-cos-security-token", "<token>")// 获取预签名presignedURL, err := c.Object.GetPresignedURL(ctx, http.MethodGet, name, tak, tsk, time.Hour, opt)if err != nil {fmt.Printf("Error: %v\\n", err)return}// 通过预签名访问对象resp, err := http.Get(presignedURL.String())if err != nil {fmt.Printf("Error: %v\\n", err)}defer resp.Body.Close()fmt.Println(presignedURL.String())fmt.Printf("resp:%v\\n", resp)// 方法2 通过 tag 设置 x-cos-security-token// 获取预签名presignedURL, err = c.Object.GetPresignedURL(ctx, http.MethodGet, name, tak, tsk, time.Hour, token)if err != nil {fmt.Printf("Error: %v\\n", err)return}// 通过预签名访问对象resp, err = http.Get(presignedURL.String())if err != nil {fmt.Printf("Error: %v\\n", err)}defer resp.Body.Close()fmt.Println(presignedURL.String())fmt.Printf("resp:%v\\n", resp)}
使用案例:自定义域名预签名下载请求
package mainimport ("context""fmt""github.com/tencentyun/cos-go-sdk-v5""net/http""net/url""os""time")func main() {// 通过环境变量获取密钥// 环境变量 SECRETID 表示用户的 SecretId,登录访问管理控制台查看密钥,https://console.cloud.tencent.com/cam/capiak := os.Getenv("SECRETID") // 用户的 SecretId,建议使用子账号密钥,授权遵循最小权限指引,降低使用风险。子账号密钥获取可参见 https://cloud.tencent.com/document/product/598/37140// 环境变量 SECRETKEY 表示用户的 SecretKey,登录访问管理控制台查看密钥,https://console.cloud.tencent.com/cam/capisk := os.Getenv("SECRETKEY") // 用户的 SecretKey,建议使用子账号密钥,授权遵循最小权限指引,降低使用风险。子账号密钥获取可参见 https://cloud.tencent.com/document/product/598/37140// 修改成用户的自定义域名u, _ := url.Parse("https://<自定义域名>")b := &cos.BaseURL{BucketURL: u}c := cos.NewClient(b, &http.Client{})name := "exampleobject"ctx := context.Background()// 获取预签名presignedURL, err := c.Object.GetPresignedURL(ctx, http.MethodGet, name, ak, sk, time.Hour, nil)if err != nil {fmt.Printf("Error: %v\\n", err)return}// 通过预签名访问对象resp, err := http.Get(presignedURL.String())if err != nil {fmt.Printf("Error: %v\\n", err)}defer resp.Body.Close()fmt.Println(presignedURL.String())fmt.Printf("resp:%v\\n", resp)}
使用案例:预签名添加请求参数或请求头部
package mainimport ("context""fmt""github.com/tencentyun/cos-go-sdk-v5""net/http""net/url""os""time")func main() {// 替换成您的临时密钥tak := os.Getenv("SECRETID") // 用户的 SecretId,建议使用子账号密钥,授权遵循最小权限指引,降低使用风险。子账号密钥获取可参见 https://cloud.tencent.com/document/product/598/37140tsk := os.Getenv("SECRETKEY") // 用户的 SecretKey,建议使用子账号密钥,授权遵循最小权限指引,降低使用风险。子账号密钥获取可参见 https://cloud.tencent.com/document/product/598/37140u, _ := url.Parse("https://examplebucket-1250000000.cos.ap-guangzhou.myqcloud.com")b := &cos.BaseURL{BucketURL: u}c := cos.NewClient(b, &http.Client{})name := "exampleobject"ctx := context.Background()// PresignedURLOptions 提供用户添加请求参数和请求头部opt := &cos.PresignedURLOptions{// http 请求参数,传入的请求参数需与实际请求相同,能够防止用户篡改此 HTTP 请求的参数Query: &url.Values{},// http 请求头部,传入的请求头部需包含在实际请求中,能够防止用户篡改签入此处的 HTTP 请求头部Header: &http.Header{},}// 添加请求参数, 返回的预签名 url 将包含该参数opt.Query.Add("x-cos-security-token", "<token>")// 添加请求头部,返回的预签名 url 只是将请求头部设置到签名里,请求时还需要自行设置对应的 header。opt.Header.Add("Content-Type", "text/html")// SDK 默认签入 Header Host,不传递 signHost 参数或者 SignHost = true 时,表示签入 Header Host。// signHost = false 时,表示不签入 Header Host,不签入 Header Host 可能导致请求失败或安全漏洞。var signHost bool = true// 获取预签名, 签名中携带host。presignedURL, err := c.Object.GetPresignedURL(ctx, http.MethodPut, name, tak, tsk, time.Hour, opt, signHost)if err != nil {fmt.Printf("Error: %v\\n", err)return}// 通过预签名访问对象req, _ := http.NewRequest(http.MethodPut, presignedURL.String(), strings.NewReader("test"))// 请求时需要设置对应 headerreq.Header.Set("Content-Type", "text/html")resp, err := http.DefaultClient.Do(req)if err != nil {fmt.Printf("Error: %v\\n", err)}defer resp.Body.Close()fmt.Println(presignedURL.String())fmt.Printf("resp:%v\\n", resp)}