2012-06-26 16 views
5

私は非常に単純なアプリケーションを書いて、特定の条件で自分のツイッターステータスを更新しました。私はtwitterのドキュメントを使用して、OAuth署名の作成要件とAuthorizationヘッダーの構造を理解しました。 PHPでcURLでリクエストを送信します。OAuthで認証できないのはなぜですか?

TwitterのDEVサイトにOAuthのツールを使用し、私は両方の私の署名ベース文字列と認可ヘッダを比較し、両者が正確に同じである。

署名ベース文字列

POST&https%3A%2F%2Fapi.twitter.com%2F1%2Fstatuses%2Fupdate.json&oauth_consumer_key%3DYNxxxxxxxxxxxWnfI6HA%26oauth_nonce%3D31077a3c7b7bee4e4c7e2b5185041c12%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1340729904%26oauth_token%3D2991771-4csoiO2fxmWgSxxxxxxxxxxDjWj2AbyxATtiuadNE%26oauth_version%3D1.0%26status%3Dblah%2520test%2520blah. 

認可ヘッダー

Authorization: OAuth oauth_consumer_key="YN4FLBxxxxxxxxxxI6HA", oauth_nonce="31077a3c7b7bee4e4c7e2b5185041c12", oauth_signature="M2cXepcxxxxxxxxxxAImeAjE%2FHc%3D", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1340729904", oauth_token="2991771-4cxxxxxxxxxxSmRvjzMoooMDjWj2AbyxATtiuadNE", oauth_version="1.0" 

明らかに私はomeの文字をxとするとデータを隠すことができますが、文字の2つの文字を比較すると全く同じ結果が得られます。参考までに、OAuthツールが生成するタイムスタンプとノンスをハードコードして、私の値をチェックのために同じにすることができます。私のアクセスレベルは読み取りと書き込みに設定されています。その同じページには、コマンドラインでcURLを使用して実行する最後の例があります。このコマンドを実行すると、問題なく完全に動作し、私のtwitterフィードに投稿されます。

これまで考えてきたことは、これまでに作成したものはすべて問題ではないと思います。以前に述べた詳細を生成するコードを投稿しているとは思いません。しかし、私は電話をかけるために使用するコードは、カールを使用して、私が犯人だと思うが、なぜ言うことができない。

<?php 
// ... 
$curl = curl_init(); 

curl_setopt($curl, CURLOPT_URL, $baseUrl); 
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); 
curl_setopt($curl, CURLOPT_POST, true); 
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); 
curl_setopt($curl, CURLOPT_HTTPHEADER, array("Authorization: $header")); 
curl_setopt($curl, CURLOPT_POSTFIELDS, array('status' => $status)); 
$result = json_decode(curl_exec($curl)); 
curl_close($curl); 

var_dump($result); 

注意を$baseUrl$header$statusは、署名を生成する際に使用したのと同じ変数であることをベースストリングと承認ヘッダーが一致しています。

実行があるページの出力:

object(stdClass)#1 (2) { ["error"]=> string(34) "Could not authenticate with OAuth." ["request"]=> string(23) "/1/statuses/update.json" } 

私は正しい方向に私を指すために誰かのためにここに十分な詳細があります願っています!

+0

https://dev.twitter.com/discussions/305(URLを確認するなど)とhttps://dev.twitter.com/discussions/308(HTTPSオプションの確認など)を確認しましたか? – Will

+0

残念ながら、はい。私が言ったように、署名ベースの文字列と承認ヘッダーはまったく同じであり、コマンドラインのカールが完全に機能するので、これらのどちらでもないことができます。 – LeonardChallis

+0

全く同じ問題がありました。ありがとう! – bozdoz

答えて

2

apache_request_headers()でテストし、私のデータは大丈夫だったし、それは問題が敷設場所のcURLだったという考えにこだわり、私はカールが明らかに、multipart/form-data;として要求のContent-typeを設定し、境界情報を追加したことに気づきましたより長いContent-Lengthフィールドもあります。これは、状態が正しく送信されなかったことを意味しました。私は、不正な形式のmultipart/form-data;要求のために推測します。

解決策は文字列として送信することでした。例えば、この作品:

curl_setopt($curl, CURLOPT_POSTFIELDS, 'status='. rawurlencode($status)); 

をしかし、私もよりよい方法があることがわかった(特に私は、配列を使用したい複数の値を持つ):非常に良く私見を探します

$postfields = array('status' => $status); 
curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($postfields)); 

1

あなたのnonceだと思います。 docsから: "oauth_nonceパラメータは、アプリケーションがそれぞれ固有の要求"(emphasis mine)に対して生成する固有のトークンです。

注意:OAuth 1 + PHPではなく、OAuth 2 + JavaまたはJavaScriptに精通しています。

実際のHTTPリクエスト(WireSharkなど)と、そのページに記載されているサンプルリクエストとを比較することができます(唯一のことではありません)。 「ヘッダー文字列を作成する」のメモも役に立ちます。はるかに検索した後

+0

誰がノンスを生成したのかを区別する方法はありません。私が言ったように、オーソライゼーションヘッダとベースストリングはまったく同じ*ですので、カールを通って走っているので、ノンスを最初に生成した人は気にしません。 nonceは、値を比較するためにハードコードされていました。私はHTTPリクエストを比較する方法があると思います。実際に '$ baseUrl'を自分のページに変更し、cURLコマンドラインとPHP cURLコールでテストしましたが、何も明らかになっていません。 – LeonardChallis

+0

Twitterはノンスをキャッシュしてリピートを拒否し、リプレイ攻撃を防ぎます。 http://oauth.net/core/1.0/#nonceを参照してください: "消費者は、そのタイムスタンプを持つすべての要求に一意のNonce値を生成します.NONCEはランダムな文字列であり、各要求に対して一意に生成されます。サービスプロバイダは以前に要求が行われたことがないことを確認し、HTTPなどの非セキュアなチャネルを介して要求が行われた場合に再生攻撃を防止するのに役立ちます。 – Will

+1

私はあなたが私を理解しているとは思わない。 nonceをハードコードする唯一の時間は、私の認証ヘッダーと署名ベースの文字列をtwitterの生成された文字列と比較することです。私は生成されたcURL要求を、それが完了することを確認するために一致させたときにテストしました。私は、同じスクリプトをPHPスクリプトで再び使用しようとはしません。 **ノンスではありません**。私のスクリプトでは、一意のノンスを生成する関数があります。しかし、あなたの入力をありがとう。 – LeonardChallis