cos签名-xml接口-算法实现

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命令,直接在命令行请求,可以获取到数据。

完整源码:点击打开链接

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值