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を使った