生成预签名 URL

最近更新时间:2024-08-13 11:18:21

我的收藏

简介

本文介绍对象存储 COS 通过 C SDK 实现生成对象预签名链接的示例代码和描述。

注意事项

2024年1月1日后创建的桶 不支持使用默认域名在浏览器预览文件,建议您配置自定义域名,详情请参见 存储桶切换自定义域名
生成预签名 URL 支持使用永久密钥或临时密钥。
获取签名/预签名函数,默认签入 Header Host;您也可以选择不签入 Header Host,但可能导致请求失败或安全漏洞。

相关示例

功能名称
描述
示例代码
生成预签名 URL
对象存储(Cloud Object Storage,COS)支持使用预签名 URL 进行对象的上传、下载,原理是将签名嵌入 URL 生成签名链接。

使用案例

生成预签名 URL

方法原型

int cos_gen_presigned_url_safe(const cos_request_options_t *options,
const cos_string_t *bucket,
const cos_string_t *object,
const int64_t expire,
http_method_e method,
cos_table_t *headers,
cos_table_t *params,
int sign_host,
cos_string_t *presigned_url);

请求示例

// COS 的 bucket 名称, [bucket]-[appid], 如: mybucket-1253666666,可在 https://console.cloud.tencent.com/cos5/bucket 查看
char bucket_name[] = "examplebucket-12500000000";
// 开发者访问 COS 服务时拥有的用户维度唯一资源标识,用以标识资源,可在 https://console.cloud.tencent.com/cam/capi 页面获取
char appid[] = "12500000000";
// 开发者拥有的项目身份ID/密钥,可在 https://console.cloud.tencent.com/cam/capi 页面获取
char secret_id[] = "AKIDXXXXXXXX";
char secret_key[] = "1A2Z3YYYYYYYYYY";
//endpoint 是 COS 访问域名信息(不设置存储桶前缀,访问 COS 时会自动在前面拼接上[bucket]-[appid]), 详情请参见 https://cloud.tencent.com/document/product/436/6224 文档
char endpoint[] = "cos.ap-guangzhou.myqcloud.com";
// 是否使用自定域名。如果设置为 COS_TRUE ,则访问 COS 时需要将 endpoint 的值修改为自定义域名
int is_cname = COS_FALSE;
void init_test_config(cos_config_t* config, int is_cname) {
cos_str_set(&config->endpoint, endpoint);
cos_str_set(&config->access_key_id, secret_id);
cos_str_set(&config->access_key_secret, secret_key);
cos_str_set(&config->appid, appid);
// cos_str_set(&config->sts_token, token); // 使用临时密钥时的 token
config->is_cname = is_cname; // 是否使用自定义域名
}
void init_test_request_options(cos_request_options_t* options, int is_cname) {
options->config = cos_config_create(options->pool);
init_test_config(options->config, is_cname);
options->ctl = cos_http_controller_create(options->pool, 0);
}
void log_status(cos_status_t* s) {
cos_warn_log("status->code: %d", s->code);
if (s->error_code)
cos_warn_log("status->error_code: %s", s->error_code);
if (s->error_msg)
cos_warn_log("status->error_msg: %s", s->error_msg);
if (s->req_id)
cos_warn_log("status->req_id: %s", s->req_id);
}

void get_presigned_url_demo()
{
char object_name[] = "test.txt"; // 对象名称
cos_pool_t *p = NULL;
cos_request_options_t *options = NULL;
cos_string_t bucket;
cos_string_t object;
cos_string_t presigned_url;
cos_table_t *params = NULL;
cos_table_t *headers = NULL;
int sign_host = 1;
cos_pool_create(&p, NULL);
options = cos_request_options_create(p);
init_test_request_options(options, is_cname);
cos_str_set(&bucket, bucket_name);
cos_str_set(&object, object_name);
cos_gen_presigned_url(options, &bucket, &object, 300, HTTP_GET, &presigned_url);
printf("presigned_url: %s\\n", presigned_url.data);
// 添加您自己的params和headers
params = cos_table_make(options->pool, 0);
//cos_table_add(params, "param1", "value");
headers = cos_table_make(options->pool, 0);
//cos_table_add(headers, "header1", "value");
// 强烈建议sign_host为1,这样强制把host头域加入签名列表,防止越权访问问题
cos_gen_presigned_url_safe(options, &bucket, &object, 300, HTTP_GET, headers, params, sign_host, &presigned_url);
printf("presigned_url_safe: %s\\n", presigned_url.data);
cos_pool_destroy(p);
}
int main() {
if (cos_http_io_initialize(NULL, 0) != COSE_OK) {
exit(1);
}
get_presigned_url_demo();
// cos_http_io_deinitialize last
cos_http_io_deinitialize();
return 0;
}

参数说明

参数名称
参数描述
类型
options
COS 请求选项
Struct
bucket
存储桶名称,存储桶的命名格式为 BucketName-APPID,此处填写的存储桶名称必须为此格式
String
object
Object 名称
String
expire
签名有效时间,单位为秒
Int
method
HTTP 请求方法枚举类型,分别为 HTTP_GET、HTTP_HEAD、HTTP_PUT、HTTP_POST、HTTP_DELETE
Enum
headers
COS 请求附加头域
Struct
params
COS 请求操作参数
Struct
sign_host
是否对 host 头域进行签名,为了安全性强烈建议开启
Int
presigned_url
生成的请求预签名 URL
String

返回结果说明

返回结果
描述
类型
code
错误码
Int

生成预签名上传 URL 并使用该 URL 上传对象

说明:
本样例仅用 libcurl 进行演示。

请求示例

//需额外加入以下头文件
#include <curl/curl.h>

void get_presigned_url_demo() {
char object_name[] = "test.txt"; // 对象名称
cos_pool_t* p = NULL;
cos_request_options_t* options = NULL;
cos_string_t bucket;
cos_string_t object;
cos_string_t presigned_url;
cos_table_t* params = NULL;
cos_table_t* headers = NULL;
int sign_host = 1;

cos_pool_create(&p, NULL);
options = cos_request_options_create(p);
init_test_request_options(options, is_cname);
cos_str_set(&bucket, bucket_name);
cos_str_set(&object, object_name);

// 添加您自己的params和headers
params = cos_table_make(options->pool, 0);
// cos_table_add(params, "param1", "value");
headers = cos_table_make(options->pool, 0);
// cos_table_add(headers, "header1", "value");

// 强烈建议sign_host为1,这样强制把host头域加入签名列表,防止越权访问问题
cos_gen_presigned_url_safe(options, &bucket, &object, 300, HTTP_PUT, headers, params, sign_host, &presigned_url);
printf("presigned_url_safe: %s\\n", presigned_url.data);

int retryIndex = 0;
while (1) {
CURL* curl;
CURLcode res;

curl_global_init(CURL_GLOBAL_DEFAULT);

curl = curl_easy_init();
if (curl) {
// 设置 URL,包括请求路径和参数
char* url = presigned_url.data;
long http_code = 0;

// 设置请求头
struct curl_slist* headers = NULL;
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);

// 设置请求体数据
char body[] = "put object with presigned url";
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, body);

// 执行 PUT 请求
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PUT");
res = curl_easy_perform(curl);

if (res == CURLE_OK && curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code) == CURLE_OK) {
// 5xx 重试3次
if (http_code / 100 != 5 || retryIndex >= 3) {
// 清理
curl_easy_cleanup(curl);
curl_slist_free_all(headers);
break;
}
}

printf("will retry, retryIndex: %d\\n", retryIndex);
retryIndex++;
// 清理
curl_easy_cleanup(curl);
curl_slist_free_all(headers);
}
curl_global_cleanup();
}
cos_pool_destroy(p);
}