2010年05月16日

OAuth への道 ―― C++で、OAuth認証(ただし、単純な Bot 限定)

さて、最終的に、OAuth 認証ヘッダを作成して、Bot として動作できそうなところに来ました。
実は、私が管理しているのは、「節気さんシリーズ」といいまして、単純に生成したメッセージを(とりあえず、メッセージを生成するまでの過程はそれなりに複雑)単純にポストするだけのものです。
ですから、Twitter へのリクエストは、POST http://api.twitter.com/1/statuses/update.xml のみです。(一応レスポンスのコードはチェックしていますが)

まず、非常におおざっぱに言いますと、Basic 認証であろうと、OAuth 認証であろうと、送信するヘッダ、ボディはほとんど同じです。
Authorization: Basic (Basic 認証ヘッダ)が
Authorization: OAuth (OAuth 認証ヘッダ)に変わるだけです。

というわけで、OAuth 認証ヘッダを生成できれば、Botとして動作可能というわけです。

----------- OAuth 認証ヘッダ作成プログラム -----------------
こんなのを作りました。

ヘッダファイル : create_oauth.h : http://www.axis.blue/tec/create_oauth.h
ソースファイル : create_oauth.cpp : http://www.axis.blue/tec/create_oauth.cpp

※上記のソースの中で、

#include <system.hpp>
#include <Classes.hpp>

の2行と、

void makeNonce() にある、 AnsiString time = Now().FormatString("yyyy/mm/dd-hh:nn:ss");
int UnixTime(TDateTime aTime) や、void makeTimeStamp() にある、Now() や、TDateTime 型は、Turbo C++ の処理系に依存しています。

別の処理系では、
AnsiString time = Now().FormatString("yyyy/mm/dd-hh:nn:ss");
は、単純に、time = "aaajajajajaja"; // ランダムな文字
とかで良いはずです。

時刻系のものは、なんとか、Unix Time を算出してください。(Visua C++ なら、CTime が使える気がします。

さらに、AnsiString も、処理系依存です。
こちらは、ほぼ、std::string で書き直せると思います。

これが、OAuth 認証ヘッダの生成に使うソースになります。

------------- 具体的にポスト ----------------------------

まず、単純に、abcd という文字をポストすることにします。
ボディは、 status=abcd です。

また、基本情報として、

OAuthDataDef mine =
{
"My_API_Name", // これは実際には使いません
"my_Consumer_key", // 実際には、入手した Consumer_key 以下同じ
"my_Consumer_secret",
"my_Access_Token",
"my_Access_Token_Secret"
};

と元になるキーを定義しておきます。
また、Body は、

char *body = "status=abcd";

とでもしておきます。

さて、このあと、

makeNonce(); // Nonce の生成
makeTimeStamp(); // timestamp の生成

AnsiString key = mine.Consumer_secret;
key += "&";
key += mine.Access_Token_Secret;
// ここまで、HMAC-SHA1 の鍵生成

AnsiString baseString = makeBaseString(mine, body);
// Base string を生成して

makeSignHere(baseString, key);
// シグネチャーを作って、

AnsiString oauthHeadder = makeHeadder(mine, body);
// OAuth 認証ヘッダを生成

となります。
create_oauth の内部構造が整理できていないので、呼び出しはこの順番でなければなりません。

※例によって、AnsiString は、処理系依存です。これも、std::string で置き換えられると思います。

ここまでで、OAuth ヘッダが生成できました。あとは、これを送信するだけです。
すでに、コネクションが成立したという前提で、(さらに、server->SendTo() でテキストが送信できるという前提で)

まず、"Content-Length: を生成します。

const char * CRLF = "\x0d\x0a";

AnsiString lenHeader = "Content-Length: ";
lenHeader += std::strlen(body);
lenHeader += CRLF;

で、

server->SendText("POST http://api.twitter.com/1/statuses/update.xml HTTP/1.1" CRLF);
server->SendText("Host: api.twitter.com" CRLF);
server->SendText("Content-type: application/x-www-form-urlencoded" CRLF);

oauthHeadder += CRLF;
server->SendText(oauthHeadder);
server->SendText(lenHeader);
server->SendText(CRLF);

server->SendText(line);
server->SendText(CRLF);

となります。
あとは、レスポンスを待つことになります。

【補足】

上記の例では、単純化するため、送信テキストを、"abcd" にしました。
しかし実際には、日本語を送信することが多いでしょう。
たとえば、
status=おはよう
であれば、UTF-8 で、URLエンコードしますから、実際に送るテキストは、

status=%E3%81%8A%E3%81%AF%E3%82%88%E3%81%86

になります。
シグネチャーを作成するための Base Text では、ここからさらに ERL エンコードされるので、Base Text の中では、
status%3D%25E3%2581%258A%25E3%2581%25AF%25E3%2582%2588%25E3%2581%2586
となります。

このあたり、最初ちょっと気がつきませんでした。
posted by 麻野なぎ at 11:06| Comment(0) | TrackBack(0) | Twitter と Bot の周辺
この記事へのコメント
コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント:

この記事へのトラックバックURL
http://blog.sakura.ne.jp/tb/38139016

この記事へのトラックバック