自分の無知さ加減を思い知ったのでメモっておく。泥縄、付け焼き刃注意。


TypePad Atom API Documentation

TypePad Atom API - TypePad Developer Resources

WSSE認証

ドキュメントより引用

Username
The username that the user enters (the TypePad username).
Nonce
A secure token generated anew for each HTTP request.
Created
The ISO-8601 timestamp marking when Nonce was created.
PasswordDigest
A SHA-1 digest of the Nonce, Created timestamp, and the password that the user supplies, base64-encoded. In other words, this should be calculated as:
base64(sha1(Nonce . Created . Password))

実装

$nonce = pack('H*', sha1(md5(time().rand().uniqid(rand(), true))));
$created = gmdate('Y-m-d\TH:i:s') . 'Z';
$digest = base64_encode(pack('H*', sha1($nonce . $created . $pass)));
$wsseHeader = sprintf('UsernameToken Username="%s", PasswordDigest="%s", Created="%s", Nonce="%s"', $user, $digest, $created, $nonce);

はまったところ

$digestの形式をどうまとめるかで悩む。あと、WSSE用ヘッダの構成順序も。結論を見てみると紆余曲折あって一番最初に戻ってるような気もしないでもないけど、最初他のプログラムから持ってきたときには、WSSE用ヘッダに渡すときに$nounceをbase64エンコードしてたりなんか地味に色々変わってた。そのあたりは、WSSEの仕様が策定されたときにNonceの仕様が明確ではなかったことに原因があるそう。pack()も付けてみたり外してみたり。いや、そちらはあって当然だとは思うんですけれどもね。




POST

ドキュメントより引用

To post an entry to a weblog, send a POST request to the PostURI.

You can specify a category for a weblog post in the optional ement http://purl.org/dc/elements/1.1/subject, which should be the category of the weblog entry. This should be a string taken from the list of available categories obtained by retrieving the list of categories in the weblog.

If the entry is successfully posted, the response will consist of a 201 Created response code.

Request:

POST /t/atom/weblog/blog_id=1 HTTP/1.1
Host: www.typepad.com
X-WSSE: my credentials

<?xml version="1.0" encoding="utf-8"?>
<entry xmlns="http://purl.org/atom/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/">
<title>Trip to the Lake</title>
<dc:subject>Vacation</dc:subject>
<content type="application/xhtml+xml" mode="xml"><div xmlns="http://www.w3.org/1999/xhtml"><img src="http://example.typepad.com/photos/vacation/lake-thumb.jpg" /> Here is a picture of me at the lake.</div></content>
</entry>

実装

$entry = '<?xml version="1.0" encoding="UTF-8"?>'
       . '<entry xmlns="http://purl.org/atom/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/">'
       . '<title>Trip to the Lake</title>'
       . '<content type="application/xhtml+xml" mode="xml"><div xmlns="http://www.w3.org/1999/xhtml"><img src="http://example.typepad.com/photos/vacation/lake-thumb.jpg" /> Here is a picture of me at the lake.</div></content>'
       . '</entry>'
;
$request = new HTTP_Request($postUri);
$request->addHeader('Accept','application/x.atom+xml, application/xml, text/xml, */*');
$request->addHeader('X-WSSE', $wsseHeader);
$request->addHeader('Content-Type', 'application/x.atom+xml');
$request->setMethod(HTTP_REQUEST_METHOD_POST);
$request->addRawPostData($entry);
$request->sendRequest();

はまったところ

$entryの形式については例が出ていたのだけど、その渡し方で悩む。何度渡しても「何渡してくれてんのかよくわかんねーよ」(500)といって怒られる。結局、ヘッダにContent-Typeが指定されていなくて恐らくtext/plainで解釈されていたためで追加したら問題なく201 Createdが返ってきた。解決後、HTTPの基本が解っていないことがわかってかなりゾッとした。





以下、自分用メモ。

WSSE認証について

WSSE認証とは、パスワードを平文で渡すのではなく暗号化して渡すことで認証させる仕組みのこと。

認証に当たってはリクエスト毎に固有の文字列(Nonce)とその文字列を生成した日時(Created)とをキーとして準備し、それをパスワードと組み合わせてサービスによって指定された方式で暗号化したもの(Digest)を生成。さらにユーザー名とそれらキー、DigestをWSSEで決められた形式で文字列化してヘッダーとして渡す。

…という感じの理解で良いんだろうか。
最初にパスワードを生成するときに暗号化されていない形で送信されるのでそのところにリスクはあるけれどもそれ以降は比較的安全なんじゃないかという気がする。

今現在は仕様もきっちり確定されているようだけど、初期はNonceの仕様が明確でなかったり、WSSEヘッダー用文字列の書き順が明確でなかったり(今でも2通りあるみたい)したために、サービスによってその辺りブレがあるのが現実っぽい。ちゃんとドキュメント読んでその辺確認した上でコードを書くべき。

ちなみにWSSEを採用しているサービスって言うと、はてなとmixiあたりか。



Atom APIの仕様について

この辺に細かいところまできっちり決められてるので迷ったら読む。

The AtomAPI



PEAR::HTTP_Requestのメソッドについて

マニュアルだと使用例くらいしかないので、困ったらこちらで確認。

Docs For Class HTTP_Request



TypePadについて

有料サービスだからか、有効な情報は殆ど落ちてない。中身は殆どMovableTypeだからそれで検索しても良いけど、MovableTypeでAtom API使ってる人ってのも殆どいなくて少なくとも初心者向けテキストはない。TypePadといえばココログの中身なのでココログで検索すれば多少は情報が集まるけど今度は精度が拡散しちゃうのでそれまた微妙。そんなもんですかねー。あらかじめちゃんと知識あって最低限のドキュメントさえあれば組み立てられるような感じじゃないと厳しいし、そうじゃない限りやるべきじゃないんかも。

ちなみにログイン時に求められる情報が「ユーザー名」から「メールアドレス」に変更になっているにもかかわらず、あらゆるドキュメントに「ユーザ名が必要だ」と書かれていてちょっと戸惑った。ニックネームとか使ってみたりしたけど何のことはない、WSSEでもユーザー名はメールアドレスでOKだった。ドキュメントの変更漏れないしは注釈不足かな。技術者ならそんくらい直感で分かれって事かも知れないけどね。確かに。