1

我正在尝试通过 oAuth 连接到 Twitter。我正在向 API https://api.twitter.com/oauth/request_token发出 POST 请求。

这是我的基本签名字符串的示例

POST&https%3A%2F%2Fapi.twitter.com%2Foauth%2Frequest_token&oauth_callback%3Dhttp%253A%252F%252Fapi.ec2.phunware.com%252Fapi%252Ftwitter%26oauth_consumer_key%3D6jq5dNZcccoPbApAJ0sOaA%26oauth_nonce%3DN2ZiMjViYzhlMDUxNDIyZWIwYjQ4NmU0ZjM1MDg4NTY%3D%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1362843354%26oauth_version%3D1.0

我使用工具http://quonos.nl/oauthTester/来验证我的基本签名。

这是对应的标题

OAuth oauth_callback="http%3A%2F%2Fapi.ec2.phunware.com%2Fapi%2Ftwitter",oauth_consumer_key="6jq5dNZcccoPbApAJ0sOaA",oauth_nonce="N2ZiMjViYzhlMDUxNDIyZWIwYjQ4NmU0ZjM1MDg4NTY=",oauth_signature_method="HMAC-SHA1",oauth_signature="7ney2RxElbHUl2t1Jnz57pQpmFs%3D",oauth_timestamp="1362843354",oauth_version="1.0" 

我在我的 MAC 终端中尝试了以下命令

curl --request 'POST' 'https://api.twitter.com/oauth/request_token' --header 'Authorization: OAuth oauth_callback="http%3A%2F%2Fapi.ec2.phunware.com%2Fapi%2Ftwitter",oauth_consumer_key="6jq5dNZcccoPbApAJ0sOaA",oauth_nonce="N2ZiMjViYzhlMDUxNDIyZWIwYjQ4NmU0ZjM1MDg4NTY=",oauth_signature_method="HMAC-SHA1",oauth_signature="7ney2RxElbHUl2t1Jnz57pQpmFs%3D",oauth_timestamp="1362843354",oauth_version="1.0"' --verbose

我得到 401 未经授权的错误。我试图设置 oauth_callback ="oob" 但我仍然得到同样的错误。

请帮忙。我正在使用 Blackberry Native SDK 进行编码。我在这里粘贴代码。通过 Blackberry 10.1 Simulator 尝试时出现 204 错误。

QByteArray Twitter::generateTimeStamp()
{
   QDateTime current = QDateTime::currentDateTime();
   uint seconds = current.toTime_t();
   return QString::number(seconds,10).toUtf8();
}

QByteArray Twitter::generateNonce()
{
    QString nonce = QUuid::createUuid().toString();
    nonce.remove(QRegExp("[^a-zA-Z\\d\\s]"));
    qDebug()<< nonce.toUtf8();
    return nonce.toUtf8().toBase64();
}

QByteArray Twitter::generateSignatureBase(const QUrl& url, HttpMethod method, const QByteArray& timestamp, const QByteArray& nonce,bool addCallbackURL)
{
    QList<QPair<QByteArray, QByteArray> > urlParameters = url.encodedQueryItems();
    QList<QByteArray> normParameters;

    QListIterator<QPair<QByteArray, QByteArray> > i(urlParameters);
    while(i.hasNext()){
            QPair<QByteArray, QByteArray> queryItem = i.next();
            QByteArray normItem = queryItem.first + '=' + queryItem.second;
            normParameters.append(normItem);
    }

    //consumer key
    normParameters.append(QByteArray("oauth_consumer_key=") + consumer->consumerKey());

    //token
    if(accessToken != NULL){
            normParameters.append(QByteArray("oauth_token=") + accessToken->oauthToken());
    }

    //signature method, only HMAC_SHA1
    normParameters.append(QByteArray("oauth_signature_method=HMAC-SHA1"));
    //time stamp
    normParameters.append(QByteArray("oauth_timestamp=") + timestamp);
    //nonce
    normParameters.append(QByteArray("oauth_nonce=") + nonce);
    //version
    normParameters.append(QByteArray("oauth_version=1.0"));

    //callback url
    if(addCallbackURL)
        normParameters.append(QByteArray("oauth_callback=") + QByteArray(CALLBACK_URL).toPercentEncoding());

    //OAuth spec. 9.1.1.1
    qSort(normParameters);
    qDebug()<<normParameters;
    QByteArray normString;
    QListIterator<QByteArray> j(normParameters);
    while (j.hasNext()) {
        normString += j.next().toPercentEncoding();
        normString += "%26";
    }
    normString.chop(3);
    qDebug()<<normString;
    //OAuth spec. 9.1.2
    QString urlScheme = url.scheme();
    QString urlPath = url.path();
    QString urlHost = url.host();
    QByteArray normUrl = urlScheme.toUtf8() + "://" + urlHost.toUtf8() + urlPath.toUtf8();

    QByteArray httpm;

    switch (method)
    {
        case GET:
                httpm = "GET";
                break;
        case POST:
                httpm = "POST";
                break;
        case DELETE:
                httpm = "DELETE";
                break;
        case PUT:
                httpm = "PUT";
                break;
    }
    qDebug()<<"signature base="<<httpm + '&' + normUrl.toPercentEncoding() + '&' + normString;
    //OAuth spec. 9.1.3
    return httpm + '&' + normUrl.toPercentEncoding() + '&' + normString;
}

QByteArray Twitter::generateAuthorizationHeader( const QUrl& url, HttpMethod method,bool addCallbackURL )
{
    QByteArray timeStamp = generateTimeStamp();
    QByteArray nonce = generateNonce();

    QByteArray baseString = generateSignatureBase(url, method, timeStamp, nonce,addCallbackURL);
    QByteArray key = consumer->consumerSecret() + '&';
    if(accessToken != NULL)
        key = key + accessToken->oauthTokenSecret();
    QByteArray signature =  HMACSH1::hmacSha1(key,baseString).toPercentEncoding();
    QByteArray header;
    header += "OAuth ";
    if(addCallbackURL)
        header += "oauth_callback=\"" + QByteArray(CALLBACK_URL).toPercentEncoding() + "\",";
    header += "oauth_consumer_key=\"" + consumer->consumerKey() + "\",";
    header += "oauth_nonce=\"" + nonce + "\",";
    header += "oauth_signature_method=\"HMAC-SHA1\",";
    header += "oauth_signature=\"" + signature + "\",";
    header += "oauth_timestamp=\"" + timeStamp + "\",";
    if(accessToken != NULL)
           header += "oauth_token=\"" + accessToken->oauthToken() + "\",";
    header += "oauth_version=\"1.0\"";
    qDebug()<<"header =" <<header;
    return header;
}

void Twitter::requestForToken()
{
    QUrl url(TWITTER_REQUEST_TOKEN_URL);
    QByteArray oauthHeader = generateAuthorizationHeader(url, POST,true);

    QNetworkRequest req(url);
    req.setRawHeader("Authorization", oauthHeader);
    req.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
    req.setHeader(QNetworkRequest::ContentLengthHeader,"0");

    QNetworkReply *reply = networkAccessManager->post(req, QByteArray());
    connect(networkAccessManager, SIGNAL(finished ( QNetworkReply*)), this, SLOT(tokenFetchSuccessfull(QNetworkReply*)));
    connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(tokenFetchFailed(QNetworkReply::NetworkError)));
    qDebug()<<"Request For Token";
}
4

1 回答 1

1

您提到您使用的是 Native SDK,您是否也在使用 Cascades?如果是这样,使用GitHub中的bb-cascades-oauth库可能会更好。它内置了对 OAuth1 和 OAuth2 的支持。

此外,根据此处找到的提示,时间戳不正确似乎是一个常见问题,因此请确保您的模拟器具有正确的日期和时间。

此处的另一位开发人员发现http://quonos.nl/oauthTester/需要一个不正确的双转义标头,并在发出实际身份验证请求时导致 401 错误。我注意到您使用了相同的测试器,并且在上面的基本签名字符串中也有双重转义,所以您可能想尝试不使用双重转义。

于 2013-03-21T17:40:52.590 回答