3

我目前正在按照此处描述的方法为 Twitter 整合授权功能:https ://dev.twitter.com/docs/auth/implementing-sign-twitter 。我正在使用 Ajax 发送我的 POST 'http' 请求,但我一直在遇到 '401: Unauthorized' 错误。我的代码如下:

function getTweets() {
    var time = generateTimestamp(); 
    var nonce = generateNonce();
    var signature = generateSignature(time, nonce);
    var headers = {
          "Authorization": 'OAuth oauth_callback="http%3A%2F%2Fwww.google.com%2F", oauth_consumer_key="eEeAAz9fakedtAOlIUhPgQ", oauth_nonce="bbc34b2ca6faabogus6dfc025907fa334", oauth_signature="' + signature + '", oauth_signature_method="HMAC-SHA1", oauth_timestamp="' + time + '", oauth_version="1.0"'
    };

    $.ajax({
        type: "POST",
        url: "https://api.twitter.com/oauth/request_token",
        dataType: "text",
        headers: headers,
        success: function(data) {
            alert("Success!");
            console.log(data);
        },
        error: function(jq) {
            alert("Request Failed.");
            console.log(jq.statusText);
        }
    });
}

function generateTimestamp() {
    var currentTime = new Date;
    currentTime = Math.floor(currentTime.getTime() / 1000);
    return currentTime;
}

function generateNonce() {
    var code = "";
    for (var i = 0; i < 20; i++) {
        code += Math.floor(Math.random() * 9).toString();
    }
    return code;
}  

function generateSignature(timestamp, nonce) {
    var http_method = "POST";
    var base_url = "https://api.twitter.com/oauth/request_token";
    var consumer_key = "eEeAAz9hUKtdjunkeIUhPgQ";
    var consumer_secret = "c7wHxnjubxVDcc5hYFqnotactuallymysecretWs2XazUFde0lPRBtBQ";
    var signature_method = "HMAC-SHA1";
    var token = "609493744-kNPzLKSI4Hg9NWQnopeFPb91eXFUutFm1nZ2hDk2";
    var token_secret = "15WOJS9Ji1AXsKRkyAZrxKdsalted5Gj5ZyEAb9aVrJxI";
    var version = "1.0";
    var parameter_string = "oauth_callback=" + encodeURIComponent(base_url) + "&oauth_consumer_key=" + consumer_key + "&oauth_nonce=" + nonce + "&oauth_consumer_key=" + consumer_key + "&oauth_signature_method=" + signature_method + "&oauth_timestamp=" + timestamp +"&oauth_version=" + version; 
    var base_string = http_method + "&" + encodeURIComponent(base_url) + "&" + encodeURIComponent(parameter_string);
    var signing_key = encodeURIComponent(consumer_secret) + "&";  
    var signature = encodeURIComponent(window.btoa(CryptoJS.HmacSHA1(base_string, signing_key)));
    alert(signature);
    return signature;
}

如果有任何其他信息可以使此错误更清楚,请随时在下面发布。谢谢。

4

1 回答 1

1

我创建了一个 node.js 库来处理 Twitter OAuth 舞蹈和 API。代码在这里, tweeter.js

欢迎您了解创建标头和签名的逻辑(从第348行开始)

我在您发布的代码中没有看到的一件事会产生巨大的影响,那就是必须生成签名字符串以包含原始标题,然后必须使用生成的字符串重建标题。这是一个巨大的痛苦,我花了一段时间才弄清楚。

虽然我写的代码是针对 node.js 的,但是你应该能够重用很多逻辑来满足你的需求。

编辑
我发现一个名为hueniverse的网站很好地记录了 OAuth。事实上,这里有一个实用程序可以构建您自己的标头来验证您的逻辑(选择“创建您自己的”单选按钮)。

编辑 2

为了更好地解释oauth_signature在标题中包含值,假设您拥有到目前为止的所有数据:

var headerObj = {
    oauth_consumer_key="123456789",
    oauth_token="11111",
    oauth_nonce="asdfghjkl%3B",
    oauth_timestamp="1341852000",
    oauth_signature_method="HMAC-SHA1",
    oauth_version="1.0"
};

您创建 HMAC-SHA1 签名并接收:"jBpoONisOt5kFYOrQ5fHCSZBGkI%3D"

然后,您将该返回值添加到headerObj,为您提供:

headerObj = {
    oauth_consumer_key="123456789",
    oauth_token="11111",
    oauth_nonce="asdfghjkl%3B",
    oauth_timestamp="1341852000",
    oauth_signature_method="HMAC-SHA1",
    oauth_version="1.0",
    oauth_signature="jBpoONisOt5kFYOrQ5fHCSZBGkI%3D"
};

而这个 headerObj 的修改版本是您构建 HTTP 标头的基础。

GET / HTTP/1.1
Host: api.twitter.com:443
Authorization: OAuth realm="https://api.twitter.com/",
    oauth_consumer_key="123456789",
    oauth_token="11111",
    oauth_nonce="asdfghjkl%3B",
    oauth_timestamp="1341852000",
    oauth_signature_method="HMAC-SHA1",
    oauth_version="1.0",
    oauth_signature="jBpoONisOt5kFYOrQ5fHCSZBGkI%3D"

注意:我没有验证主机/领域/端口,所以这些可能是错误的。检查那些 API。

这样做的原因是,在 Twitter 方面(这是一个 OAuth 实现细节),该oauth_signature值被删除并且标头的其余部分被散列并且它的返回值与发送的值进行比较oauth_signature。这有点像信封上的蜡封……如果标题其余部分的哈希值与您发送的哈希值不匹配oauth_signature,Twitter 就知道不信任发件人或内容。

编辑 2.5

我正在将其从评论移至答案。

如果您查看tweeter.js 中的这一行,您将看到其中的逻辑。

   var signature = self.oauthSignature(method, path, headerObj, query);
    headerObj.oauth_signature = qs.escape(signature);

    // concat the header object into a csv string
    var header = 'OAuth realm="Twitter API",';
    var oauthParts = [];
    for (var h in headerObj) {
        oauthParts.push(h + '="'+headerObj[h]+'"');
    }
    header+= oauthParts.join(',');

    //...

    return header;

这段代码就像我在 EDIT 2 中解释的那样,通过将 JSON 对象转换为key="value"存储在 中的字符串oauthParts[],然后将该数组中的每个元素连接成一个以逗号分隔的字符串,该字符串以OAuth realm="Twitter API",

于 2012-06-30T01:23:09.360 回答