逆にこの時確かにそうなる。

逆に,このとき与式は確かに恒等式になる

Perl/CGIで、TwitterのOAuth認証をやる

Perlをまともに使いこなせない初心者のため、OAuthのライブラリ?の使い方が分からなかった。
だから、1からOAuth認証のコードを書いた。CGIとしてサーバ上で動かしている。
汚かったりへんてこりんな僕のコードをブログに書くのは初めてで恥ずかしいが、書いてみるなり。
OAuthの説明は省略する。そもそも仕様書をちゃんと読んでいない......英語...

まずは token と token_secret を取得する
$key='XXXXXXXXXXXXXXXXXXXXXXX'; #アプリケーションごとに与えられたconsumer_key
$secret='YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY&'; #同様に与えられたconsumer_secret 末尾に&をつける
$method='HMAC-SHA1'; #署名方式(Twitterではこれに固定)
$time=time; #現在時刻
$nonce=time*7; #ユニークな値。時間に7をかけるのはダメだと思うけど自分で使う分にはいいや
$ver='1.0'; #バージョン


#これだけそろったら、次に、signatureを作る準備をする

$data="GET&http%3A%2F%2Fapi.twitter.com%2Foauth%2Frequest_token&oauth_consumer_key%3D$key%26oauth_nonce%3D$nonce%26oauth_signature_method%3D$method%26oauth_timestamp%3D$time%26oauth_version%3D$ver";
use Digest::HMAC_SHA1 qw(hmac_sha1 hmac_sha1_hex);
use MIME::Base64;
$digest = encode_base64(hmac_sha1($data, $secret)); #HMAC-SHA1でハッシュ化
$digest =~ s/([^\w ])/'%'.uc(unpack('H2', $1))/eg; #URLエンコード
$digest =~ s/\%0A//g; #URLエンコード


#そしてtokenとtoken_secret取得

use LWP::Simple;
$datum=get("http://api.twitter.com/oauth/request_token?oauth_consumer_key=$key&oauth_nonce=$nonce&oauth_signature_method=$method&oauth_timestamp=$time&oauth_version=$ver&oauth_signature=$digest");

これで、$datumのなかに、oauth_tokenとoauth_token_secretが入ったので、適当に取り出す。
この時に、oauth_tokenとoauth_token_secretをどこかに保存して、後から取り出せるようにしておく。

認証させる
#手に入れたoauth_tokenは$oauth_tokenに入れたとする
$URI="http://api.twitter.com/oauth/authorize?oauth_token=$oauth_token";
print "Location: $URI\n\n";

ユーザに、アプリケーションを認証してもらう。
この時に、コールバックがある場合と、無い場合で挙動が分かれる。

コールバックが無い場合

認証後に、6ケタのPINコードが表示されるので、ユーザに入力してもらう。ここでは、$PINに入力してもらったとする。
ちなみに別のCGIファイルで動かしている。

#$keyや$secretなどは最初のと同様
#保存しておいたoauth_tokenを$oauth_tokenへ、oauth_token_secretを$oauth_token_secretへ代入してある

$secret=$secret.$oauth_token_secret; #2種類のsecretをくっつける

$data="GET&http%3A%2F%2Fapi.twitter.com%2Foauth%2Faccess_token&oauth_consumer_key%3D$key%26oauth_nonce%3D$nonce%26oauth_signature_method%3D$method%26oauth_timestamp%3D$time%26oauth_token%3D$oauth_token%26oauth_verifier%3D$PIN%26oauth_version%3D$ver";


#あとはまた同様に取得する

use Digest::HMAC_SHA1 qw(hmac_sha1 hmac_sha1_hex);
use MIME::Base64;
$digest = encode_base64(hmac_sha1($data, $secret));
$digest =~ s/([^\w ])/'%'.uc(unpack('H2', $1))/eg; #URLエンコード
$digest =~ s/\%0A//g; #URLエンコード

use LWP::Simple;
$datum=get("http://api.twitter.com/oauth/access_token?oauth_consumer_key=$key&oauth_nonce=$nonce&oauth_signature_method=HMAC-SHA1&oauth_timestamp=$time&oauth_token=$token&oauth_verifier=$PIN&oauth_version=$ver&oauth_signature=$digest");

これで、$datumの中に、oauth_token、oauth_token_secret、user_id、screen_nameが入ったので適当に取り出す。
oauth_tokenと、oauth_secret、それからconsumer_keyとconsumer_secretがあればつぶやきなどの投稿等ができる。

コールバックがある場合

認証後に戻ってきた先。
$ENV{'QUERY_STRING'}に、oauth_verifyが入っているので、これを$PINに代入。あとはコールバックが無い場合と同じ。


まとめ

これで一応TwitterでのOAuth認証は終わり。。。
これ合っているのかな。でも実際に動いているので間違ってはいないと信じているけれど.....
変数名とかおかしなところがあるかもしれない。

やっかいなのはURLエンコード
ツイートをpostするときに、2回URLエンコードしないといけない場合が出てくる。
ブラウザアプリの場合は、最初からURLエンコードされた値をURLエンコードするからいいけれど、
生の文字列の場合は、1回ブラウザのようにURLエンコードしてから、URLエンコードしないと動かなかった。

$tweet='ついったーなう';
$tweet =~ s/([\W])/'%'.uc(unpack('H2', $1))/eg;#生のツイートをブラウザ送信のようにURLエンコード
$tweet =~ s/\+/%20/g;$twee=$tweet;
$tweet =~ s/([^a-zA-Z0-9\.\-\~\_])/'%'.uc(unpack('H2', $1))/eg; #URLエンコード
$tweet =~ s/\%0A//g;
#$tweeを使うところと、$tweetを使うところがあるので注意
#生のデータをPOSTするときは、$tweeを、HMAC-SHA1するときは、$tweetを使った