微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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,string>& user_headers);



Auth.cpp

// 腾讯云签名算法文档:https://qcloud.com/document/product/436/7778
std::string Auth::AppSignXml(uint64_t app_id,string>& _user_params,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命令,直接在命令行请求,可以获取到数据。

完整源码:点击打开链接

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。