Amazon

2011年3月26日土曜日

Opensocialアプリの署名付きリクエスト

mixi Developer Centerにmixiアプリから外部へリクエストするさいに署名付きリクエストを送る方法の記載があるが、Pythonを使ってサーバーサイドロジックを書いている身としては、PHPやJavaのコードで書かれていても困る。。。

ということで調べてみたらこちらのサイトにまさしくビンゴな内容が。
基本的に上記サイトを参照して頂くとして


----- 以下、引用
そこで mixiアプリからのリクエストを検証するサンプルを書いてみました。
利用するためには、次の2つのライブラリが必要です。
これらを 次のように App Engine のプロジェクト直下に置いてください。
nantoka-project/
|-- Crypto/
|-- app.yaml
|-- index.py
|-- index.yaml
|-- oauth.py
|-- signed_request.py
Cryptoは、下のようにすると簡単に入手できます。
% svn export http://gdata-python-client.googlecode.com/svn/trunk/src/gdata/Crypto
準備ができたら、さっそく使ってみます。使い方は、モジュールをインポートして、署名を検証したいリクエスト・メソッドのデコレータとして指定します。動いているアプリケーションに下線部分を追加するだけです。


from google.appengine.ext import webappimport wsgiref.handlers
from signed_request import signed_request
class Index(webapp.RequestHandler):
    @signed_request
    def get(self):
        # do something
        self.response.headers['Content-Type'] = 'text/plain'
        self.response.out.write('OK')
def main():
    application = webapp.WSGIApplication(
        [('/', Index),],
        debug=True)
    wsgiref.handlers.CGIHandler().run(application)
if __name__ == "__main__":
    main()
以上。

だけだと素っ気ないので、signed_request.py の中身を簡単に説明します。通常なら OAuth のクライアントライブラリを使って簡単にできそうなものですが、Google App Engine では openssl のライブラリが使えないので、多くのコンテナで採用されている RSA-SHA1 形式の署名を検証するには少し工夫する必要があります。外部サーバの呼び出し » mDCのページに記載されている公開鍵を mixi.cer という名前のテキストファイルに保存します。そして、この公開鍵を16進数表記に変換します。
% openssl x509 -modulus -noout < mixi.cer | sed s/Modulus=/0x/
B5BAB9467B3920492D5E5759FB7EC58E56AF9EE73826EC2B0F817EE0
D43057056D479CB0560D7411A9D759218801B505C7A865A6960E6F4C
7FDCF04C1BCD3AE372E65D2266BEFE1589150197662CF487B62FF0FD
2954170D68098F1046AA8E4C3BAAC0FC8A7BF246E235B210254209B5
BB896562F72CC55EEA6A483B64948B55
signed_request.py 中の MIXI_CERT がこれに当たります。他のコンテナに対応させる場合も同様に変換すれば OK です。
* 上記の16進数表記は、変更された後(2011/3/26現在)のmixiの公開鍵を適用しています。

なお、自分の開発環境(Aptana + Python 2.7)ではsigned_request.pyの中の
local_hash = hashlib.sha1(message).digest()
の一行で .sha1がundefined variableエラーを出したままでしたが、とりあえずそのままにしました。
-----

上記がサーバーサイドロジックの変更点。
続いてクライアント側の変更点。
これまで外部へのリクエストを作成する際にgadgets.io.RequestParameters.AUTHORIZATIONパラメータをgadgets.io.AuthorizationType.NONEにしていたら、それをgadgets.io.AuthorizationType.SIGNEDに変更する。付加していなかったのなら追加する。

params[gadgets.io.RequestParameters.METHOD] = gadgets.io.MethodType.GET;
params[gadgets.io.RequestParameters.CONTENT_TYPE] = gadgets.io.ContentType.TEXT;
params[gadgets.io.RequestParameters.AUTHORIZATION] = gadgets.io.AuthorizationType.SIGNED;

これでリクエストは通るはず。
デコレータを付与した関数に対して、ブラウザから直接アクセスすると"Invalid OAuth Signature."と表示されたので、とりあえずはうまく動いている様子。

0 件のコメント:

コメントを投稿

Amazon3