2008-12-01 Mon
WSSE認証を利用したAtom APIとか
動機
いろんなWeb APIを触ってみようと思った。
できた物
- WSSE.py (ファイル前半)
WSSE認証
このへんを見ながらちょこちょこと作り始めました。
送信プロトコル
WSSE認証をする場合はまずサービスのエンドポイントに特定のHTTPリクエストを送る必要があります。PythonでHTTPリクエストを送る場合にはhttplibのHTTPConnectionメソッドを使います。
HTTPリクエストのHTTPヘッダにはX-WSSEプロパティにbase64にエンコードした各ユーザ名、パスワードなどを送信する必要があります。
- リクエスト
GET /_atom/blog HTTP/1.1 X-WSSE: UsernameToken Username="user_name", PasswordDigest="fSzKHSagDuwiAWR092gIteMLgwo=", Nonce="MmtxM2Z2aTV0djQx", Created="2005-06-04T13:44:30Z" Host: blog.so-net.ne.jp
プロパティのエンコード方法とかはこんな感じ
Username -- ユーザー名。(はてなフォトライフAPIでははてなアカウントのid)
Nonce -- HTTPリクエスト毎に生成したセキュリティ・トークン*1
Created -- Nonceが作成された日時をISO-8601表記で記述したもの
PasswordDigest -- Nonce, Created, パスワード(はてなアカウントのパスワード)を文字列連結しSHA1アルゴリズムでダイジェスト化して生成された文字列を、Base64エンコードした文字列
WSSEプロパティ作成部分のコードはこんな感じ
def createHeaderToken(userid, password): nonce = sha.sha(str(time.time() + random.random())).digest() nonce64 = base64.encodestring(nonce).strip() created = datetime.datetime.now().isoformat() + 'Z' passdigest = sha.sha(nonce + created + password).digest() pass64 = base64.encodestring(passdigest).strip() wsse = 'UsernameToken Username="%(u)s", PasswordDigest="%(p)s", Nonce="%(n)s", Created="%(c)s"' value = dict(u = userid, p = pass64, n = nonce64, c = created) return wsse % value
その後エンドポイントにリクエストを送ります。その部分はこんな感じ。
def atomRequest(self, wsse, method, endpoint, body, content_type): header_info = {'X-WSSE': wsse, 'Content-Type': content_type, 'Authorization': 'WSSE profile="UsernameToken"', 'User-Agent': 'Python WSSE'} conninfo = urllib.splittype(endpoint) conntypeinfo = conninfo[0] connhostinfo = urllib.splithost(conninfo[1]) conn = httplib.HTTPConnection(connhostinfo[0]) conn.request(method, connhostinfo[1], body, header_info) r = conn.getresponse() if r.status in [200, 201]: raise Exception('login failure') response = dict(status = r.status, reason = r.reason, data = r.read()) conn.close() return response
基本的な流れとしては
- ルートエンドポイントにHTTPリクエストを送る
- サービスエンドポイントのURLをHTTPレスポンスによって得る
- サービスエンドポイントに各種メソッド(GET/POST/PUT/DELETE)を使って必要なデータを送信する
という感じです。上記のatomRequest()はとりあえずHTTPリクエストを送って、HTTPレスポンスを得る部分でのイディオムとなっています。
- 868 http://kamo.pos.to/dpoke/
- 845 http://www.google.co.jp/search?q=mixi+API&lr=lang_ja&ie=utf-8&oe=utf-8&aq=t&rls=org.mozilla:ja:official&client=firefox-a
- 484 http://www.google.co.jp/search?q=mixi+api&ie=utf-8&oe=utf-8&aq=t&rls=org.mozilla:en-US:official&client=firefox-a
- 233 http://www.google.co.jp/search?hl=ja&client=firefox-a&rls=org.mozilla:ja:official&hs=lb6&q=Firefox+タブで開く&btnG=検索&lr=lang_ja
- 229 http://www.google.co.jp/search?sourceid=navclient&hl=ja&ie=UTF-8&rlz=1T4GGLJ_jaJP173JP173&q=ssh+NAT+Linux+VMware+ゲストOS
- 179 http://www.google.co.jp/search?q=mixi+api&sourceid=navclient-ff&ie=UTF-8&rlz=1B5GGGL_jaJP301JP302
- 156 http://www.google.co.jp/search?hl=ja&q=mixi+api&sourceid=navclient-ff&rlz=1B5GGGL_jaJP309JP309&ie=UTF-8
- 145 http://kamo.pos.to/dpoke/c/internet_258.html
- 122 http://www.google.co.jp/search?aq=f&sourceid=chrome&ie=UTF-8&q=mixi+API
- 121 http://www.google.co.jp/hws/search?hl=ja&q=mixi+API&client=fenrir&channel=&adsafe=off&safe=off&lr=lang_ja
