云数据库 TableStorage

    C++开发示例

    我们在写下边的示例代码时,为了简单清楚,便于理解,忽略了一些错误处理,用户基于以下示例开发的时候,可以自行补齐。

    生成认证字符串

    在访问云数据库 TableStorage 时,每个访问都需要使用用户的AK/SK生成认证字符串来进行身份认证,参考百度智能云鉴权认证机制百度智能云认证字符串生成代码示例

    // 我们在这里定义了一个HttpRequest结构体,在后续的demo中我们会使用到此结构体
    struct HttpRequest {
        HttpRequest() {
            // 只支持ContentType为json
            headers["Content-Type"] = "application/json";
        }
        std::string method;
        std::string path;
        std::map<std::string, std::string> headers;
        std::map<std::string, std::string> params;
        std::string body;
    };

    生成认证字符串的c++函数定义如下。

    我们在这里定义了一个根据HttpRequest生成认证字符串的函数,实现见本页最下方的百度智能云认证字符串C++实现,其它语言的实现可参考百度智能云认证字符串生成代码示例

    std::string gen_authorization(const HttpRequest& request, int timestamp);

    创建Instance

    当用户开通云数据库 TableStorage 服务后,需要先创建一个instance。

    create instance demo
    void create_instance() {
        // 获取当前时间戳
        time_t timestamp = time(NULL);
        // 初始化HttpRequest
        HttpRequest http_request;
        // 方法为PUT表示创建资源
        http_request.method = "PUT";
        // 将创建名为ins_demo的instance
        http_request.path = "/v1/instance/ins_demo";
        // 注意Http请求中的x-bce-date与生成认证字符串的时间需一致
        http_request.headers["x-bce-date"] = utcfromtimestamp(timestamp);
        http_request.headers["Host"] = "bts.bd.baidubce.com";
        http_request.headers["Authorization"] = gen_authorization(http_request, timestamp);
     
        // 使用curl发送请求
        CURL* curl = curl_easy_init();
        struct curl_slist* curl_headers = NULL;
        // 填充header
        for (auto const& item : http_request.headers) {
            std::string header = item.first + ":" + item.second;
            curl_headers = curl_slist_append(curl_headers, header.c_str());
        }
        // 拼接Url
        std::string url("http://bts.bd.baidubce.com");
        url.append(http_request.path);
        // 设置Url
        curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
        // 设置headers
        curl_easy_setopt(curl, CURLOPT_HTTPHEADER, curl_headers);
        // 设置method
        curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, http_request.method.c_str());
        // 发送请求
        curl_easy_perform(curl);
        // 解析http返回码
        long http_code = -1;
        curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code);
        // 清理curl
        curl_easy_cleanup(curl);
    }

    创建Table

    用户在创建好Instance后,就可以在Instance中创建表了,下边的示例是创建一张默认结构的表,如果用户对于表结构有特别需求,可参考API参考增加参数。

    void create_table() {
        // 获取当前时间戳
        time_t timestamp = time(NULL);
        // 初始化HttpRequest
        HttpRequest http_request;
        // 方法为PUT表示创建资源
        http_request.method = "PUT";
        // 将在ins_demo中创建名为table_demo的table
        http_request.path = "/v1/instance/ins_demo/table/table_demo";
        // 注意Http请求中的x-bce-date与生成认证字符串的时间需一致
        http_request.headers["x-bce-date"] = utcfromtimestamp(timestamp);
        http_request.headers["Host"] = "bts.bd.baidubce.com";
        http_request.headers["Authorization"] = gen_authorization(http_request, timestamp);
     
        // 使用curl发送请求
        CURL* curl = curl_easy_init();
        struct curl_slist* curl_headers = NULL;
        // 填充header
        for (auto const& item : http_request.headers) {
            std::string header = item.first + ":" + item.second;
            curl_headers = curl_slist_append(curl_headers, header.c_str());
        }
        // 拼接Url
        std::string url("http://bts.bd.baidubce.com");
        url.append(http_request.path);
        // 设置Url
        curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
        // 设置headers
        curl_easy_setopt(curl, CURLOPT_HTTPHEADER, curl_headers);
        // 设置method
        curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, http_request.method.c_str());
        // 发送请求
        curl_easy_perform(curl);
        // 解析http返回码
        long http_code = -1;
        curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code);
        // 清理curl
        curl_easy_cleanup(curl);
    }

    向Table写入数据

    用户创建好Table后,就可以向Table写入数据。

    void insert() {
        // 获取当前时间戳
        time_t timestamp = time(NULL);
        // 初始化HttpRequest
        HttpRequest http_request;
        // 方法为PUT表示创建资源,即写入数据
        http_request.method = "PUT";
        // 将向ins_demo中的表table_demo中写入一行数据
        http_request.path = "/v1/instance/ins_demo/table/table_demo/row";
        // 拼接写入的数据,为json格式,并且数据要经过UrlEncode
        // 写入rowkey(主键)为"www.baidu.com/0"的两列数据:col1,值为"val1",col2,值为"val2"
        http_request.body =
            "{"
                "\"rowkey\":\"www.baidu.com%2F0\","
                "\"cells\":["
                "{"
                    "\"column\":\"col1\","
                    "\"value\":\"val1\""
                "},"
                "{"
                    "\"column\":\"col2\","
                    "\"value\":\"val2\""
                "}"
            "]}";
        // 注意Http请求中的x-bce-date与生成认证字符串的时间需一致
        http_request.headers["x-bce-date"] = utcfromtimestamp(timestamp);
        http_request.headers["Host"] = "bts.bd.baidubce.com";
        http_request.headers["Content-Length"] = std::to_string(http_request.body.size());
        http_request.headers["Authorization"] = gen_authorization(http_request, timestamp);
     
        // 使用curl发送请求
        CURL* curl = curl_easy_init();
        struct curl_slist* curl_headers = NULL;
        // 填充header
        for (auto const& item : http_request.headers) {
            std::string header = item.first + ":" + item.second;
            curl_headers = curl_slist_append(curl_headers, header.c_str());
        }
        // 拼接Url
        std::string url("http://bts.bd.baidubce.com");
        url.append(http_request.path);
        // 设置Url
        curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
        // 设置headers
        curl_easy_setopt(curl, CURLOPT_HTTPHEADER, curl_headers);
        // 设置method
        curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, http_request.method.c_str());
        // 设置body
        curl_easy_setopt(curl, CURLOPT_POSTFIELDS, http_request.body.c_str());
        // 发送请求
        curl_easy_perform(curl);
        // 解析http返回码
        long http_code = -1;
        curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code);
        // 清理curl
        curl_easy_cleanup(curl);
    }

    从Table读取数据

    一般来说,读取数据时,用户需要解析所读取的内容,所以我们在读示例里增加了curl获取返回内容的代码。用户可以指定rowkey从Table中读取数据。

    // curl回调方法,用于读出返回的content,即body内容
    size_t content_data(void* buffer, size_t size, size_t nmemb, void* userp) {
        *((std::string*)userp) = *((std::string*)userp) +
                                std::string((const char*)buffer, size * nmemb);
        return size * nmemb;
    }
    // curl回调方法,用于读出返回的header
    size_t header_data(void* buffer, size_t size, size_t nmemb, void* userp) {
        *((std::string*)userp) = *((std::string*)userp) +
                                std::string((const char*)buffer, size * nmemb);
        return size * nmemb;
    }
     
    void query() {
        // 获取当前时间戳
        time_t timestamp = time(NULL);
        // 初始化HttpRequest
        HttpRequest http_request;
        // 方法为GET表示获取资源
        http_request.method = "GET";
        // 将向ins_demo中的table_demo读取一条数据
        http_request.path = "/v1/instance/ins_demo/table/table_demo/row";
        // 拼接单条读请求,为json格式,并且数据要经过UrlEncode
        // 读取rowkey(主键)为"www.baidu.com/0"的两列数据:col1和col2
        // 如果需要读整行数据,则只需要设置rowkey即可
        http_request.body =
            "{"
                "\"rowkey\":\"www.baidu.com%2F0\","
                "\"cells\":["
                "{"
                    "\"column\":\"col1\""
                "},"
                "{"
                    "\"column\":\"col2\""
                "}"
            "]}";
        // 注意Http请求中的x-bce-date与生成认证字符串的时间需一致
        http_request.headers["x-bce-date"] = utcfromtimestamp(timestamp);
        http_request.headers["Host"] = "bts.bd.baidubce.com";
        http_request.headers["Content-Length"] = std::to_string(http_request.body.size());
        http_request.headers["Authorization"] = gen_authorization(http_request, timestamp);
     
        // 使用curl发送请求
        CURL* curl = curl_easy_init();
        struct curl_slist* curl_headers = NULL;
        // 填充header
        for (auto const& item : http_request.headers) {
            std::string header = item.first + ":" + item.second;
            curl_headers = curl_slist_append(curl_headers, header.c_str());
        }
        // 拼接Url
        std::string url("http://bts.bd.baidubce.com");
        url.append(http_request.path);
        // 设置Url
        curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
        // 设置headers
        curl_easy_setopt(curl, CURLOPT_HTTPHEADER, curl_headers);
        // 设置method
        curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, http_request.method.c_str());
        // 设置body
        curl_easy_setopt(curl, CURLOPT_POSTFIELDS, http_request.body.c_str());
        // 设置返回的header,content
        // 如果你不需要解析header和content,则不需要做此设置,返回的content也会直接打印到标准输出
        std::string header;
        std::string content;
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, content_data);
        curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, header_data);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &content);
        curl_easy_setopt(curl, CURLOPT_HEADERDATA, &header);
        // 发送请求
        curl_easy_perform(curl);
        // 解析http返回码
        long http_code = -1;
        curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code);
        // 清理curl
        curl_easy_cleanup(curl);
        // 打印返回的header内容
        printf("query response header: %s.\n", header.c_str());
        // 打印返回的content内容,为json格式,具体可参考api文档
        // 如果你需要对返回的内容做下一步处理,可以将此content按json格式解析后作为后续使用
        printf("query result: %s.\n", content.c_str());
    }

    用户可以范围扫描数据。

    // curl回调方法,用于读出返回的content,即body内容
    size_t content_data(void* buffer, size_t size, size_t nmemb, void* userp) {
        *((std::string*)userp) = *((std::string*)userp) +
                                std::string((const char*)buffer, size * nmemb);
        return size * nmemb;
    }
    // curl回调方法,用于读出返回的header
    size_t header_data(void* buffer, size_t size, size_t nmemb, void* userp) {
        *((std::string*)userp) = *((std::string*)userp) +
                                std::string((const char*)buffer, size * nmemb);
        return size * nmemb;
    }
     
    void scan() {
        // 获取当前时间戳
        time_t timestamp = time(NULL);
        // 初始化HttpRequest
        HttpRequest http_request;
        // 方法为GET表示获取资源
        http_request.method = "GET";
        // 将向ins_demo中的table_demo读取数据
        http_request.path = "/v1/instance/ins_demo/table/table_demo/rows";
        // 拼接范围读请求,为json格式,并且数据要经过UrlEncode
        // 读取rowkey(主键)范围为[www.baidu.com/0, www.baidu.com/9)数据,并且读取其中两列:col1和col2
        // 注意includeStart和includeStop为区间的开闭,本示例中,区间为前闭后开
        // limit为1表示只返回第一行这个区间内的数据
        // rowkey区间和其它参数,用户可以参考api文档,按需配置
        http_request.body =
            "{"
                "\"startRowkey\":\"www.baidu.com%2F0\","
                "\"includeStart\":true,"
                "\"stopRowkey\":\"www.baidu.com%2F9\","
                "\"includeStop\":false,"
                "\"selector\":["
                "{"
                    "\"column\":\"col1\""
                "},"
                "{"
                    "\"column\":\"col2\""
                "}],"
                "\"limit\":1"
            "}";
        // 注意Http请求中的x-bce-date与生成认证字符串的时间需一致
        http_request.headers["x-bce-date"] = utcfromtimestamp(timestamp);
        http_request.headers["Host"] = "bts.bd.baidubce.com";
        http_request.headers["Content-Length"] = std::to_string(http_request.body.size());
        http_request.headers["Authorization"] = gen_authorization(http_request, timestamp);
     
        // 使用curl发送请求
        CURL* curl = curl_easy_init();
        struct curl_slist* curl_headers = NULL;
        // 填充header
        for (auto const& item : http_request.headers) {
            std::string header = item.first + ":" + item.second;
            curl_headers = curl_slist_append(curl_headers, header.c_str());
        }
        // 拼接Url
        std::string url("http://bts.bd.baidubce.com");
        url.append(http_request.path);
        // 设置Url
        curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
        // 设置headers
        curl_easy_setopt(curl, CURLOPT_HTTPHEADER, curl_headers);
        // 设置method
        curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, http_request.method.c_str());
        // 设置body
        curl_easy_setopt(curl, CURLOPT_POSTFIELDS, http_request.body.c_str());
        // 设置返回的header,content
        // 如果你不需要解析header和content,则不需要做此设置,返回的content也会直接打印到标准输出
        std::string header;
        std::string content;
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, content_data);
        curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, header_data);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &content);
        curl_easy_setopt(curl, CURLOPT_HEADERDATA, &header);
        // 发送请求
        curl_easy_perform(curl);
        // 解析http返回码
        long http_code = -1;
        curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code);
        // 清理curl
        curl_easy_cleanup(curl);
        // 打印返回的header内容
        printf("query response header: %s.\n", header.c_str());
        // 打印返回的content内容,为json格式,具体可参考api文档
        // 如果你需要对返回的内容做下一步处理,可以将此content按json格式解析后作为后续使用
        printf("query result: %s.\n", content.c_str());
    }

    删除Table中数据

    用户也可以指定rowkey删除Table中的某行数据。

    void remove() {
        // 获取当前时间戳
        time_t timestamp = time(NULL);
        // 初始化HttpRequest
        HttpRequest http_request;
        // 方法为DELETE表示删除资源
        http_request.method = "DELETE";
        // 将删除ins_demo中的表table_demo中的一行数据
        http_request.path = "/v1/instance/ins_demo/table/table_demo/row";
        // 拼接写入的数据,为json格式,并且数据要经过UrlEncode
        // 删除rowkey(主键)为"www.baidu.com/0"的两列数据:col1,值为"val1",col2,值为"val2"
        // 如果要将整行,则不需要设置cells,只需设置rowkey即可
        http_request.body =
            "{"
                "\"rowkey\":\"www.baidu.com%2F0\","
                "\"cells\":["
                "{"
                    "\"column\":\"col1\","
                    "\"value\":\"val1\""
                "},"
                "{"
                    "\"column\":\"col2\","
                    "\"value\":\"val2\""
                "}"
            "]}";
        // 注意Http请求中的x-bce-date与生成认证字符串的时间需一致
        http_request.headers["x-bce-date"] = utcfromtimestamp(timestamp);
        http_request.headers["Host"] = "bts.bd.baidubce.com";
        http_request.headers["Content-Length"] = std::to_string(http_request.body.size());
        http_request.headers["Authorization"] = gen_authorization(http_request, timestamp);
     
        // 使用curl发送请求
        CURL* curl = curl_easy_init();
        struct curl_slist* curl_headers = NULL;
        // 填充header
        for (auto const& item : http_request.headers) {
            std::string header = item.first + ":" + item.second;
            curl_headers = curl_slist_append(curl_headers, header.c_str());
        }
        // 拼接Url
        std::string url("http://bts.bd.baidubce.com");
        url.append(http_request.path);
        // 设置Url
        curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
        // 设置headers
        curl_easy_setopt(curl, CURLOPT_HTTPHEADER, curl_headers);
        // 设置method
        curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, http_request.method.c_str());
        // 设置body
        curl_easy_setopt(curl, CURLOPT_POSTFIELDS, http_request.body.c_str());
        // 发送请求
        curl_easy_perform(curl);
        // 解析http返回码
        long http_code = -1;
        curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code);
        // 清理curl
        curl_easy_cleanup(curl);
    }

    删除Table

    用户如果不再使用某张表,则可将其删除,其中的数据也会清理。

    void drop_table() {
        // 获取当前时间戳
        time_t timestamp = time(NULL);
        // 初始化HttpRequest
        HttpRequest http_request;
        // 方法为DELETE表示删除资源
        http_request.method = "DELETE";
        // 将删除ins_demo中名为table_demo的table
        http_request.path = "/v1/instance/ins_demo/table/table_demo";
        // 注意Http请求中的x-bce-date与生成认证字符串的时间需一致
        http_request.headers["x-bce-date"] = utcfromtimestamp(timestamp);
        http_request.headers["Host"] = "bts.bd.baidubce.com";
        http_request.headers["Authorization"] = gen_authorization(http_request, timestamp);
     
        // 使用curl发送请求
        CURL* curl = curl_easy_init();
        struct curl_slist* curl_headers = NULL;
        // 填充header
        for (auto const& item : http_request.headers) {
            std::string header = item.first + ":" + item.second;
            curl_headers = curl_slist_append(curl_headers, header.c_str());
        }
        // 拼接Url
        std::string url("http://bts.bd.baidubce.com");
        url.append(http_request.path);
        // 设置Url
        curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
        // 设置headers
        curl_easy_setopt(curl, CURLOPT_HTTPHEADER, curl_headers);
        // 设置method
        curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, http_request.method.c_str());
        // 发送请求
        curl_easy_perform(curl);
        // 解析http返回码
        long http_code = -1;
        curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code);
        // 清理curl
        curl_easy_cleanup(curl);
    }

    删除Instance

    当用户不再使用某个Instance时,可将其删除,但需要注意的是,被删除的Instance必需是空的,即其中没有表存在,否则会拒绝删除操作。

    void drop_instance() {
        // 获取当前时间戳
        time_t timestamp = time(NULL);
        // 初始化HttpRequest
        HttpRequest http_request;
        // 方法为DELETE表示删除资源
        http_request.method = "DELETE";
        // 将删除名为ins_demo的instance
        http_request.path = "/v1/instance/ins_demo";
        // 注意Http请求中的x-bce-date与生成认证字符串的时间需一致
        http_request.headers["x-bce-date"] = utcfromtimestamp(timestamp);
        http_request.headers["Host"] = "bts.bd.baidubce.com";
        http_request.headers["Authorization"] = gen_authorization(http_request, timestamp);
     
        // 使用curl发送请求
        CURL* curl = curl_easy_init();
        struct curl_slist* curl_headers = NULL;
        // 填充header
        for (auto const& item : http_request.headers) {
            std::string header = item.first + ":" + item.second;
            curl_headers = curl_slist_append(curl_headers, header.c_str());
        }
        // 拼接Url
        std::string url("http://bts.bd.baidubce.com");
        url.append(http_request.path);
        // 设置Url
        curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
        // 设置headers
        curl_easy_setopt(curl, CURLOPT_HTTPHEADER, curl_headers);
        // 设置method
        curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, http_request.method.c_str());
        // 发送请求
        curl_easy_perform(curl);
        // 解析http返回码
        long http_code = -1;
        curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code);
        // 清理curl
        curl_easy_cleanup(curl);
    }

    百度智能云认证字符串C++实现

    // 时间戳转为公有云utc时间串的函数
    // 例如:1535904000 转换为 2018-09-02T16:00:00Z
    inline std::string timestamp_to_utc(time_t timestamp) {
        struct tm* timeinfo = gmtime(&timestamp);
        const int buf_size = 32;
        char buf[buf_size];
        strftime(buf, buf_size, "%FT%TZ", timeinfo);
        return std::string(buf);
    }
    // UrlEncode实现,except_slash参数表示是否编码'/'
    inline std::string uri_encode(const std::string& src, bool except_slash = false) {
        static const char* hex = "0123456789ABCDEF";
        std::string dst = "";
        for (size_t i = 0; i < src.length(); i++) {
            char c = src[i];
            if (isalnum(c) || strchr("-_.~", c)) {
                dst += c;
            } else if (except_slash && c == '/') {
                dst += c;
            } else {
                dst += '%';
                dst += hex[(unsigned char)c >> 4];
                dst += hex[(unsigned char)c & 0xf];
            }
        }
        return dst;
    }
    // UriEncodeExceptSlash实现
    inline std::string uri_encode_except_slash(const std::string& str) {
        return uri_encode(str, true);
    }
    // 百度智能云认证字符串生成的C++实现
    // 其中有一些加密函数由于有公开库,我们这里直接调用,用户可找相应的公开库(如openssl)
    // 用户可以参考百度智能云生成认证字符串流程来阅读以下实现代码
    std::string gen_authorization(const HttpRequest& request, time_t timestamp) {
        // 1. 生成CanonicalRequest
        std::string http_method = request.method;
        // 1.1 生成CanonicalURI,
        std::string canonical_uri = uri_encode_except_slash(request.path);
        // 1.2 计算CanonicalQueryString
        std::string canonical_query = "";
        // 使用set结构暂存在后续遍历时可以保证天然字典序遍历,如果使用vector暂存需要配合sort按字典序排序
        std::set<std::string> encoded_params;
        // 对params遍历一次对kv做urlencode
        auto params_it = request.params.begin();
        for (; params_it != request.params.end(); ++params_it) {
            if (params_it->first == "authorization" || params_it->first == "Authorization") {
                continue;
            }
            std::string key = uri_encode(params_it->first);
            std::string value = uri_encode(params_it->second);
            encoded_params.insert(key + '=' + value); // 兼容value为空字符串的情形
        }
        // 对params遍历urlencode后的集合,拼接字符串
        auto enc_params_it = encoded_params.begin();
        for (; enc_params_it != encoded_params.end(); ++enc_params_it) {
            if (enc_params_it != encoded_params.begin()) {
                canonical_query += '&';
            }
            canonical_query += *enc_params_it;
        }
        // 1.3 计算CanonicalHeaders
        std::string canonical_header = "";
        // 使用set结构暂存在后续遍历时可以保证天然字典序遍历,如果使用vector暂存需要配合sort按字典序排序
        std::set<std::string> encoded_headers;
        // 对headers遍历一次,对key做转换小写、urlencoded操作,对value做去首尾空格、urlencoded操作
        auto headers_it = request.headers.begin();
        for (; headers_it != request.headers.end(); ++headers_it) {
            // 将key部分转换为全小写
            std::string key = headers_it->first;
            for (size_t i = 0; i < key.length(); ++i) {
                key[i] = ::tolower(key[i]);
            }
            // 将value部分去掉首尾的空白符
            const char* blank_chars = " \n\r\t\v";
            std::string value = headers_it->second;
            value.erase(0, value.find_first_not_of(blank_chars));
            value.erase(value.find_last_not_of(blank_chars) + 1);
            if (value.empty()) {
                continue;
            }
            std::string encoded_key = uri_encode(key);
            std::string encoded_value = uri_encode(value);
            encoded_headers.insert(encoded_key + ':' + encoded_value);
        }
        // 对headers遍历urlencode后的集合,拼接字符串
        auto enc_headers_it = encoded_headers.begin();
        for (; enc_headers_it != encoded_headers.end(); ++enc_headers_it) {
            if (enc_headers_it != encoded_headers.begin()) {
                canonical_header += '\n';
            }
            canonical_header += *enc_headers_it;
        }
        // 拼接生成CanonicalRequest
        std::string canonical_request = http_method + '\n'
                                      + canonical_uri + '\n'
                                      + canonical_query + '\n'
                                      + canonical_header;
        // 2. 生成SigningKey,这里我们直接调用了hmac_sha256函数,用户可以使用任意公开库中的HMAC-SHA256-HEX函数代替
        // 注意使用hmac_sha256函数时参数的顺序
        // 在生成鉴权串时的时间戳一定要和发送请求中Header域中的Date/x-bce-date相同
        // 用户的ak/sk
        const std::string ak = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
        const std::string sk = "ssssssssssssssssssssssssssssssss";
        // 拼接认证字符串前缀 : bce-auth-v1/{accessKeyId}/{timestamp}/{expirationPeriodInSeconds}
        std::string auth_string_prefix = "bce-auth-v1/";
        auth_string_prefix.append(ak + '/');
        auth_string_prefix.append(timestamp_to_utc(timestamp));
        // 认证字符串的超时时间(有效期)为1800秒,用户可以自行设置,时间长意味着效率高,但安全性会降低
        auth_string_prefix.append("/1800");
        std::string sign_key = hmac_sha256(auth_string_prefix, sk);
        // 3. 生成Signature
        std::string sign = hmac_sha256(canonical_request, sign_key);
        // 4. 生成认证字符串,即做拼接
        // 将前缀和Signature拼接得到完整的认证字符串
        // 与签名结果之间为两个”/”,含义是使用默认签名方式,signedHeaders内容留空
        std::string auth = auth_string_prefix + "//" + sign;
        return auth;
    }
    上一篇
    操作指南
    下一篇
    API参考