2013-06-12 83 views
0

我正在尝试开发使用Dropbox的桌面应用程序。我使用C++,libcurl(用于请求)liboauthcpp(用于身份验证)和Rest API(来自Dropbox)。错误:在Dropbox上上传文件时出现无效签名

由于我已经成功验证和一些更多的操作(列表和下载文件),我无法管理上传文件。我收到以下错误:{ “错误”: “无效的签名”}

这里是我的代码:

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); 
} 

任何想法,请?

编辑:

下面是本代码产生请求: https://api-content.dropbox.com/1/files/sandbox/?oauth_version=1.0&oauth_signature_method=PLAINTEXT&oauth_consumer_key=xxxxxxxxxxxxxxx&oauth_token=xxxxxxxxxxxxxxx&oauth_signature=xxxxxxxxxxxxxxx&xxxxxxxxxxxxxxx

响应其中O在这两种情况下得到: https://api-content.dropbox.com/1/files/sandbox/?oauth_consumer_key=xxxxxxxxxxxxxxx&oauth_nonce=13xxxxxx83cf&oauth_signature=xxxxxx%xxxxxxxxxxxxxxxxxx%xxxxx%xx&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1371107283&oauth_token=xxxxxxxxxxxxxxx&oauth_version=1.0

我与明文方法produse和请求: {“error”:“签名无效。”}

回答

1

您使用的是哪种OAuth签名方法?如果它不是纯文本,那么我相信问题在于你没有将HTTP请求的主体传递给getURLQueryString。身体需要成为已签名字符串的一部分。这就解释了为什么你能够获得几个GET的操作;这些请求没有一个机构。

附注:它看起来像你使用POST形式的文件上传,其中as the docs sayPUT复杂得多。我认为如果你改变你的生活会更好。 :-)例如,我认为您添加的submit字段可能会导致呼叫无法正常工作。

编辑:这是一个使用手动构建的明文签名的完整工作示例。填写应用程序键,应用程序的秘密,令牌和令牌密钥,并确保有一个名为“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; 
} 
+0

我觉得我通过HTTP请求的身体传递getURLQueryString,通过编写: – michalis

+0

请查看我的编辑 – michalis

+0

我也尝试过“PUT”,但我仍然得到相同的错误。 – michalis

0

有没有人用过liboauthcpp?我怀疑我的错误是在我使用getURLQueryString的方式..我传递的URL到这个函数,但我不知道我是否也必须传递数据。 不幸的是,这个库没有文档。

+0

这就是我的答案指出的。您的代码不会将HTTP请求的主体传递给'getURLQueryString'。 – smarx

相关问题