错误:在Dropbox上传文件时签名无效

时间:2013-06-12 10:13:56

标签: post dropbox libcurl signature

我正在尝试开发一个使用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);
}

请问任何想法?

编辑:

以下是本代码产生的请求: 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

以及我使用明文方法生成的请求: 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得到的响应: {“error”:“签名无效。”}

2 个答案:

答案 0 :(得分:1)

您使用的是哪种OAuth签名方法?如果它只是纯文本,那么我认为问题在于你没有将HTTP请求的主体传递给getURLQueryString。正文需要是签名字符串的一部分。这就解释了为什么你能够让一些GET操作起作用;这些请求没有正文。

旁注:看起来您正在使用文件上传的POST格式,as the docs sayPUT复杂得多。我认为如果你改变你的生活会更好。 :-)例如,我认为您添加的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传递给这个函数,但我不确定是否也必须传递数据。 不幸的是,这个库没有文档。