Twitter OAuth1.0A Javascript错误

时间:2012-06-30 01:13:54

标签: javascript ajax twitter oauth

我目前正致力于按照此处描述的方法为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;
}

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

1 个答案:

答案 0 :(得分:0)

我创建了一个node.js库来搞乱Twitter OAuth舞蹈和API。代码为here, tweeter.js

欢迎您浏览创建标题和签名的逻辑(从348行开始)

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

虽然我编写的代码面向node.js,但您应该能够重用大量逻辑来满足您的需求。

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

编辑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知道不信任发件人或内容。 / p>

编辑2.5

我正在将这一点从评论转移到答案。

如果你在tweeter.js中查看this line,你会看到逻辑。

   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;

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

开头的字符串