我正在尝试开发一个使用dropbox的桌面应用程序。我正在使用C ++,libcurl(用于请求)liboauthcpp(用于身份验证)和Rest API(用于dropbox)。
由于我已成功完成身份验证和更多操作(列表和下载文件),因此无法上传文件。我收到以下错误:{“error”:“签名无效。”}
这是我的代码:
m_upload_url = "https://api-content.dropbox.com/1/files/sandbox/";
OAuth::Consumer consumer(m_consumer_key, m_consumer_secret);
OAuth::KeyValuePairs access_token_resp_data = OAuth::ParseKeyValuePairs(m_access_token_Response);
OAuth::Token access_token = OAuth::Token::extract( access_token_resp_data );
OAuth::Client oauth = OAuth::Client(&consumer, &access_token);
string oAuthQueryString = oauth.getURLQueryString( OAuth::Http::Post, m_upload_url);
string upload_Request = (string(m_upload_url) + string("?") + oAuthQueryString);
CURL *curl;
CURLcode res;
struct curl_httppost *formpost=NULL;
struct curl_httppost *lastptr=NULL;
struct curl_slist *headerlist=NULL;
static const char buf[] = "Expect:";
curl_global_init(CURL_GLOBAL_ALL);
/* Fill in the file upload field */
curl_formadd(&formpost,
&lastptr,
CURLFORM_COPYNAME, "file",
CURLFORM_FILE, "C:/Users/Desktop/textfile.txt",
CURLFORM_END);
/* Fill in the filename field */
curl_formadd(&formpost,
&lastptr,
CURLFORM_COPYNAME, "name",
CURLFORM_COPYCONTENTS, "textfile",
CURLFORM_END);
/* Fill in the submit field too, even if this is rarely needed */
curl_formadd(&formpost,
&lastptr,
CURLFORM_COPYNAME, "submit",
CURLFORM_COPYCONTENTS, "send",
CURLFORM_END);
curl = curl_easy_init();
/* initalize custom header list (stating that Expect: 100-continue is not
wanted */
headerlist = curl_slist_append(headerlist, buf);
if(curl) {
/* what URL that receives this POST */
curl_easy_setopt(curl, CURLOPT_URL, upload_Request.c_str());
/* only disable 100-continue header if explicitly requested */
curl_easy_setopt(curl, CURLOPT_HTTPPOST, 1L);
curl_easy_setopt(curl, CURLOPT_POST, 1L);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist);
curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeFunction);
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
/* Perform the request, res will get the return code */
res = curl_easy_perform(curl);
string response = string(gData);
qDebug() << QString::fromStdString(response);
/* Check for errors */
if(res != CURLE_OK)
qDebug() << "curl_easy_perform() failed: %s\n" << curl_easy_strerror(res);
/* always cleanup */
curl_easy_cleanup(curl);
/* then cleanup the formpost chain */
curl_formfree(formpost);
/* free slist */
curl_slist_free_all (headerlist);
}
这里是writeFunction:
char gData[1024*1024];
unsigned int gDataLen = 0;
size_t writeFunction( char *ptr, size_t size, size_t nmemb)
{
memcpy( &( gData[gDataLen] ), ptr, (size * nmemb) );
gDataLen += (size * nmemb);
gData[ gDataLen ] = '\0';
return (size * nmemb);
}
请问任何想法?
编辑:
在以下两种情况下,O得到的响应: {“error”:“签名无效。”}
答案 0 :(得分:1)
您使用的是哪种OAuth签名方法?如果它只是纯文本,那么我认为问题在于你没有将HTTP请求的主体传递给getURLQueryString
。正文需要是签名字符串的一部分。这就解释了为什么你能够让一些GET
操作起作用;这些请求没有正文。
旁注:看起来您正在使用文件上传的POST格式,as the docs say比PUT复杂得多。我认为如果你改变你的生活会更好。 :-)例如,我认为您添加的submit
字段可能会导致调用无效。
编辑:这是一个使用手动构建的明文签名的完整工作示例。填写app密钥,app secret,token和token secret,并确保有一个名为“hello.txt”的文件,以便它可以工作:
#include <stdio.h>
#include <curl/curl.h>
#include <iostream>
#include <fstream>
using namespace std;
size_t read_data(void *ptr, size_t size, size_t nmeb, void *stream)
{
return fread(ptr,size,nmeb,(FILE*)stream);
}
int main(void)
{
CURL *curl;
CURLcode res;
FILE * rfp = fopen("hello.txt", "r");
string appkey = "<APP KEY>";
string appsecret = "<APP SECRET>";
string token = "<ACCESS TOKEN>";
string token_secret = "<ACCESS TOKEN SECRET>";
curl = curl_easy_init();
if(curl) {
curl_easy_setopt(curl, CURLOPT_URL, "https://api-content.dropbox.com/1/files_put/sandbox/hello.txt");
struct curl_slist *headers = NULL;
string header = "Authorization: OAuth oauth_version=\"1.0\", oauth_signature_method=\"PLAINTEXT\", oauth_consumer_key=\"" + appkey + "\", oauth_token=\"" + token + "\", oauth_signature=\"" + appsecret + "&" + token_secret + "\"";
headers = curl_slist_append(headers, header.c_str());
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl, CURLOPT_PUT, 1L);
curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_data);
curl_easy_setopt(curl, CURLOPT_READDATA, rfp);
res = curl_easy_perform(curl);
curl_slist_free_all(headers);
if(res != CURLE_OK)
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
curl_easy_cleanup(curl);
}
fclose(rfp);
return 0;
}
答案 1 :(得分:0)
有没有人使用liboauthcpp?我怀疑我的错误在于我使用getURLQueryString的方式..我将url传递给这个函数,但我不确定是否也必须传递数据。 不幸的是,这个库没有文档。