2013-06-12 82 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

相關問題