COS签名
腾讯云cos xml接口签名文档
代码
Auth.h
/// @brief 返回cos_xml接口的签名
/// 腾讯云签名文档:https://qcloud.com/document/product/436/7778
/// @param app_id 项目的app_id
/// @param secret_id 签名秘钥id,可在控制台获得
/// @param secret_key 签名秘钥,可在控制台获得
/// @param expired_time 签名文档中q_key_time,q_sign_time有效时间
/// @param uri 签名秘钥id,可在控制台获得
/// @param bucket_name bucket名字,可在控制台获得
/// @param op HTTP操作GET、PUT
/// @param user_params 用户参数
/// @param user_headers http头部
/// @return string 签名,可用于访问cos的xml接口
static std::string AppSignXml(uint64_t app_id,
const std::string& secret_id,
const std::string& secret_key,
uint64_t expired_time,
const std::string& uri,
const std::string& bucket_name,
const std::string& op,
const std::map<string,string>& user_params,
const std::map<string,string>& user_headers);
Auth.cpp
// 腾讯云签名算法文档:https://qcloud.com/document/product/436/7778
std::string Auth::AppSignXml(uint64_t app_id,
const std::string& secret_id,
const std::string& secret_key,
uint64_t expired_time,
const std::string& uri,
const std::string& bucket_name,
const std::string& op,
const std::map<string,string>& _user_params,
const std::map<string,string>& _user_headers)
{
// 将params和headers的key都转成小写(方便字典序排序)
string key,value;
std::map<string,string> user_params;
for(std::map<string, string>::const_iterator it = _user_params.begin();
it != _user_params.end(); ++it) {
key = CodecUtil::ToLower(it->first);
value = it->second;
user_params[key] = value;
}
std::map<string,string> user_headers;
for(std::map<string, string>::const_iterator it = _user_headers.begin();
it != _user_headers.end(); ++it) {
key = CodecUtil::ToLower(it->first);
value = it->second;
user_headers[key] = value;
}
// step 1: calc Signkey
char q_key_time[30]; //key有效时间
uint64_t time_s = time((time_t*)NULL); //time返回10位unix时间,单位s
snprintf(q_key_time, 30,
#if __WORDSIZE == 64
"%lu;%lu",
#else
"%llu;%llu",
#endif
time_s, time_s + expired_time);
string sign_key = CodecUtil::HmacSha1(q_key_time, secret_key);
string sign_key_str = CodecUtil::HexToStr(sign_key);
#ifdef SIGN_DEBUG
std::cout<< "***********************************************" << std::endl;
std::cout<< "**********q_key:" << q_key_time << std::endl;
std::cout<< "**********sign_key_str:\n" << sign_key_str <<std::endl;
#endif
// step 2: get FormatString
string format_str;
// operation
format_str += CodecUtil::ToLower(op);
format_str += "\n";
// uri
format_str += CodecUtil::UrlEncode(uri);
format_str += "\n";
// user_params
string params_key, params_value, param_str;
for(std::map<string, string>::const_iterator it = user_params.begin();
it != user_params.end(); ) {
params_key = it->first;
params_value = it->second;
param_str = CodecUtil::ToLower(CodecUtil::UrlComponentEncode(params_key))
+ "=" + CodecUtil::UrlComponentEncode(params_value);
format_str += param_str;
++it;
if(it != user_params.end())
format_str += "&";
}
format_str += "\n";
//user_headers
string header_key, header_value, header_str;
for(std::map<string, string>::const_iterator it = user_headers.begin();
it != user_headers.end(); ) {
header_key = it->first;
header_value = it->second;
header_str = CodecUtil::ToLower(CodecUtil::UrlComponentEncode(header_key))
+ "=" + CodecUtil::UrlComponentEncode(header_value);
format_str += header_str;
++it;
if(it != user_headers.end())
format_str += "&";
}
format_str += "\n";
string sha1_format_str = CodecUtil::GetFileSha1(format_str.c_str(),format_str.length());
#ifdef SIGN_DEBUG
std::cout<< "**********format_str:\n" << format_str <<std::endl;
std::cout<< "**********sha1_format_str:\n" << sha1_format_str <<std::endl;
#endif
// step 3: get StringToSign
char q_sign_time[30]; //sign有效时间(key有效时间一般大于或等于sign有效时间)
strcpy(q_sign_time, q_key_time);
string str2sign;
str2sign += "sha1\n";
str2sign += q_sign_time;
str2sign += "\n";
str2sign += sha1_format_str;
str2sign += "\n";
#ifdef SIGN_DEBUG
std::cout<< "**********str2sign:\n" << str2sign <<std::endl;
#endif
// step 4: calc signature
string signature = CodecUtil::HmacSha1(str2sign, sign_key_str);
string signature_str = CodecUtil::HexToStr(signature);
// step5: get Authorization
string auth;
auth += "q-sign-algorithm=sha1";
auth += "&q-ak=";
auth += secret_id;
auth += "&q-sign-time=";
auth += q_sign_time;
auth += "&q-key-time=";
auth += q_key_time;
auth += "&q-header-list="; //需要检查的header_key,字典序排列
// auth += "host;range";
for(std::map<string, string>::const_iterator it = user_headers.begin();
it != user_headers.end(); ) {
auth += CodecUtil::ToLower(it->first);
++it;
if(it != user_headers.end())
auth += ";";
}
auth += "&q-url-param-list="; //需要检查的param_key,字典序排列
for(std::map<string, string>::const_iterator it = user_params.begin();
it != user_params.end(); ) {
auth += CodecUtil::ToLower(it->first);
++it;
if(it != user_params.end())
auth += ";";
}
auth += "&q-signature=";
auth += signature_str;
#ifdef SIGN_DEBUG
std::cout<< "**********auth:\n" << auth <<std::endl<<std::endl;
std::cout<< "***********************************************" << std::endl;
#endif
return auth;
}
测试demo
请到腾讯云申请对象存储帐号,控制太获取参数填到对应位置,Make编译,curl命令运行。
int main(){
// 腾讯云示例:
// SecretKey: AKIDZfbOA78asKUYBcXFrJD0a1ICvR98JM
// SecretID: QmFzZTY0IGlzIGEgZ2VuZXJp
// 测试使用的 Bucket 是在中国华北地区的 testbucket,建立在开发商 AppID 为 125000000 的账户下
// GET Object 示例:
// 以下示例内容展示了一个 GET Object 操作的签名示例,
// 地址是 http://testbucket-125000000.cn-north.myqcloud.com/testfile
// 并通过 Range 参数请求该文件的前 4 个字节。
// GET 请求:
// GET /testfile HTTP/1.1
// Host: testbucket-125000000.cn-north.myqcloud.com
// Range: bytes=0-3
//重要的事情说三遍
//这些默认参数是腾讯云给的,但是key和id只是演示,并不能通过cos的验证。请填写自己申请的腾讯云帐号的参数
//这些默认参数是腾讯云给的,但是key和id只是演示,并不能通过cos的验证。请填写自己申请的腾讯云帐号的参数
//这些默认参数是腾讯云给的,但是key和id只是演示,并不能通过cos的验证。请填写自己申请的腾讯云帐号的参数
uint64_t app_id = 125000000;//填写自己的腾讯云appid
string secret_key = "AKIDZfbOA78asKUYBcXFrJD0a1ICvR98JM"; //填写自己的SecretKey,cos控制台查看
string secret_id = "QmFzZTY0IGlzIGEgZ2VuZXJp"; //填写自己的Secretid,cos控制台查看
uint64_t expired_time = 10000;
string bucket_name = "testbucket"; // bucket名称
string uri = "/testfile"; //cos上面bucket下面的object路径,以/开始
string op = "GET";
map<string,string> user_params;
map<string,string> user_headers;
//填写host:<bucket_name>-<app_id>.<region>.myqcloud.com
user_headers["Host"]="testbucket-125000000.cn-north.myqcloud.com";
user_headers["Range"]="bytes=0-3";
string auth1 = qcloud_cos::Auth::AppSignXml(app_id, secret_id, secret_key,
expired_time, uri, bucket_name, op, user_params, user_headers);
cout << auth1 <<endl<<endl;
cout<< "curl -v http://" + user_headers["Host"] + uri +" "\
"-H \"Accept:*/*\" -H \"Range:" + user_headers["Range"] + "\" -H \"User-Agent:curl/7.29.0\" "\
"-H \"Authorization:" << auth1 << "\"" <<endl;
return 0;
}
生成的curl命令,直接在命令行请求,可以获取到数据。