実装してみた。
仕様は前回の記事参照。
作っているうちにどんどん混乱してくるから、先にまとめておいてよかった。
今回の内容は、オフィシャルドキュメントの内容ではなく、個人的にこうやった、というまとめ。
今週の月曜日、mixiアプリが正式コンテンツになったっぽい。
mixiがやっとベータじゃなくなったらしい。
今週の金曜日、Macの新しいOS「Mac OS X Snow Leopard」が発売したらしい。
Leopardユーザは3,300円でアップグレードできるらしい。
見た目はそんなに変わらないらしいけど、90%の改良を加えたとか書いてあった。
金曜日の夜から土曜日の朝(もしくは昼)にかけて、完全趣味でやるプログラムが気持ちよくて仕方がない。
スーパー趣味プログラムタイム!!
データベースにトークン保存用のテーブルを作成
とりあえずこんな感じで。
oauth_consumer_keyも内部で保存してあるID(serial)に置き換えようかと思ったけど、めんどくさくてそのままにした。
create table oauth_token( oauth_consumer_key varchar(255) not null, oauth_callback varchar(255) not null, oauth_token varchar(255) primary key, oauth_token_secret varchar(255), oauth_verifier varchar(255), oauth_timestamp bigint not null, type enum('request','authorize','access') not null );
ランダムなトークンを生成する関数
こんな感じで。
これなら[a-zA-Z0-9]+で、文字数も非固定だから推測されにくい!
<?php function getRandomToken($c=2){ $token = ''; for($i=0;$i<$c;$i++){ $m = mt_rand()%2 ? 'sha1' : 'md5'; $token .= $m($token.microtime().mt_rand(),1); } $token = base64_encode($token); $token = str_replace(array('=','/','+'),array('','',''),$token); return $token; }
$c=2の時
QdUCr0qMfP6jEgmU1xkZpiTFIswnZA9b0Q83sD6sfnHvWyzZOcq3Q d44W9wLNCs2CPr1pmviegyijV8bXfudPlYcMYnWPugsfPpZ4Vw3lA SLmAH6fWOW3ztkBuMNZWLIvG1fUamZ4VpRxxpeipplPHm 58QmD93S0btqtIFd91LRbK5yF9TmCF2l0ZYBnmAZvjks MmAH10mfNyRBWJsx1gUhH93O3O5GSMJPVDDY81uZKTDuG19Q YD7yHoARaHGiPPrCisfN2jG3uO2MK0HXVtqKEMZp28ijzqF kIQDjnr8xWE7B98jqa0q1QqM5b5Zct49rd0X5H2CnGXht Q7bGfycQXJbsB3GT4JTihRQXLLi6efxPIrhTlNl7MmiCEOLW0CCatA YUE95nMwffv6nD1nxR7tza5vRVVqYGrMjl4CGVhjKzbFsJ5bang B6io5TqKp0eV5Vj6GKcWdzdcAVaHwZAgmi07hcTHkt4bvRacnvRjQ IITMa0SPDMgnJfzQfYthVisgaI87lLOmpHONzgtEu8cE2Z8NwDMl4A jVKzbyH23VhOdZ0g5kdreCjUQjVjiSVVKqinhF197q9UANl5 dk9TwQlUZpNN6jo8E5E0rSdBR00GzLVnaRv21aDO63PjAQB8 8M5hN9ImDsHqf0zr6CYKB0k0XWgKmvizPsZsQf90VdUpFK 6xQehSqT0gO9ZZWKVo4zdCsghZzy9j5HqzSW8qBGLN9lEKI 0ZpAmzUZxrjW0kuZe4fBIwMIWUGQecCLMzeqKhsH1VK1DrQsLlZ1mw GgZHn7ApuZDhh3uB7OuJQS5wd1SIALu6TReiLcwXplJJRFNGBSng AdMOc5R1tZyjBFOdObVKj4ItO95h70Qe3VckmQdqrti5mo itI9hNWqhabKpO8MAOg259Chh2VIdy4wKzl5kEW3EP S6kiDLNB3YWV8WGOKXonKbM9S5QrbRcZROJYAYBXtRB
$c=3の時。
M3dh28Bxw2A6oPBaScEEDvHlHDe8dmwWLqs700yBQMFvaEshXc1RUDW2G97DQqHY9IXHyx7GN9p8N6 h3GooIF4vdivG7Kwgx6iibfWpEBmyhzocOWfqmUqCehfpkbjCtOYOq5ATs7JciYjsAyA I8h0Thb4U02iK70xqNMc0tonFE1FVOJplPa6JhGNQBkvis74CHNLkFFoQyOJ2YrLA 5Id8kakGw6CW1fFmkSAZRzEME2rFyJATReZtSH8yKyTzBJ6J6ShnGASTZRMCqgQo8kTdIQ NOeDNbByChrfUVeU3BhLUk1SMhgaTRYfqm57eoCJG1dpjSSLPr6b03PKfwoabnr5t39geG81RU oThax6C2UrDihPkWRmbkBRxCBfTAX0zpjsp35Pjv4je3BlJdVbAKNKNluR85aVUq72jJAo MtWppVWoA51Y70bJvC2CZNetXkfLXaiRupR82gC1k4ZB0GhMAEcQuEgHlndh2cCzQzMv1qcME 5nQ24nXiz86F0EK7Czl4aUP1kMmPlwq6cOO57FZ6iofUP9RZbXdaaOOpvmHJKoB7EFQ TTIW5PzqqeuFcJ27D9YTXIJ68aeDMGkvwLNLvPq39QXKMNfwNgo9eus6s9oEAqHMGA0ky0cL3M 5UhjyU2tKTrltu0tYYqj9ZGjZ606ucQ6fp0VnrfETrhm8BEZ3ggsSGekJOAPpDDgy3A 5KeWIp538SLiTAbgXR1E9SY3NltmzURk0kVc6t3TX4HSNmy2coCfJjDSmaekw8zbln2IA 7xAYJ1MQ5hdzaVxbPNXK11qiQgMCF20Lejh5Thhy12FlSs6zJvgVbZAuHCjCWRpaHfD0ArVeiWLz1C K9trl9hHsXSBkpCygwScPUgvQvFXqYhg9ZB5EbmBq6okAqBHd8gK0NxidcUhFwvoi69w eKxLzwLOYFjG2VpBHjqCFQ1gTF62HyiulhVLRvDSYrpEn7hXwMKnXxkdJJ331UFA DMlagKmTb4yX5uRnYpnqLIaRUxuj4uekahTyWuw1gnMykHrwQS6W1kwAWDGsBm7AeCT69dBpFw ArEtbX6BvqT05appebcDUsjOsuRsz0L4earLgDZgFZkBHWgsDeiuWHGmQWHTIWBxF99nGm19OM 4s19C7cYitfb1Afv096KmkkeOMBFAqES8iyz05ACDjOeZUiRykXxuiqZmzHLL9vKd4bKkQtc I1PMf2K1EsvqCxnyx6Mi7ItO6nDoufXRNtNEV6fvIpAWqz6KguoBA635TtuBV QjBRRkG3FpCPDVmKpna6FK0yDXLDWoXROzsaMTcuM7oQ679OdwK74irralpWd992D9MbjT7CVV7H qJ4js2XNTI3rzu6A95vzsqsWmCIf52Be6ybcdwn0d6etOFLznBROSGhVU9wpQ2GElUFEGgnQgz6frqP
リクエストトークン発行
- OAuth認証
- 有効期限の過ぎたトークン削除
- パラメータチェック
- oauth_callback
- データベース登録
- oauth_consumer_key
- コンシューマキー
- oauth_callback
- コンシューマが送ってきたパラメータ
- oauth_token
- ランダム生成
- oauth_token_secret
- ランダム生成
- oauth_timestamp
- コンシューマが送ってきたパラメータ
- type
- 'request'
- oauth_consumer_key
- レスポンス
- oauth_token
- さっきランダム生成したoauth_token
- oauth_token_secret
- さっきランダム生成したoauth_token_secret
- oauth_callback_confirmed
- 'true'
- oauth_token
コンシューマが受け取るパラメータはこんな感じ。
レスポンスボディをparse_strした結果。
Array ( [oauth_token] => 0qu11xIjGx64NUHrsJ9jV1FvuGvBMDzTYPQzvoxTwUjL [oauth_token_secret] => 8U2YjORAoOk3hhXwbWYaiBUEwKyQf2lRhAE8wYEQxhzQzjsXccE0TrZi88t5xGbb8hug [oauth_callback_confirmed] => true )
ユーザ認証 1
認証フォームを表示。
- 有効期限の過ぎたトークン削除
- パラメータチェック
- oauth_token
- 送られてきたoauth_tokenが有効かチェック
- ユーザがログインしているかチェック
- ログインしていない場合はログインフォーム表示
- 認証チェックフォーム表示
ユーザ認証 2
ユーザは、同じURLに認証可否結果パラメータ付きでアクセスしてくる。
- 有効期限の過ぎたトークン削除
- パラメータチェック
- oauth_token
- 送られてきたoauth_tokenが有効かチェック
- ユーザがログインしているかチェック
- ログインしていない場合はログインフォーム表示
- ユーザが許可したかチェック
- データベース更新
- set
- oauth_token
- ランダム生成
- oauth_verifier
- ランダム生成
- type
- 'authorize'
- oauth_token
- where
- oauth_token
- 送られてきたoauth_token
- type
- 'request'
- oauth_token
- set
- レスポンス
- oauth_token
- さっきランダム生成したoauth_token
- oauth_verifier
- さっきランダム生成したoauth_verifier
- oauth_token
コンシューマが受け取るパラメータはこんな感じ。
$_GET。
Array ( [oauth_token] => 6IxekxUqBobCWQZgTYq7WYDveQWzg2uRSz8mnGhphY1UAWz [oauth_verifier] => B3NsPOxusGrz4nxRpb91zJYD33YzKLWZ53sy4moekno2rSvOpZFkOpCgio7fmuG7pQw )
アクセストークン発行
- OAuth認証
- 有効期限の過ぎたトークン削除
- パラメータチェック
- oauth_token
- oauth_verifier
- データベース更新
- set
- oauth_token
- ランダム生成
- oauth_token_secret
- ランダム生成
- type
- 'access'
- oauth_token
- where
- oauth_consumer_key
- コンシューマキー
- oauth_token
- 送られてきたoauth_token
- oauth_verifier
- 送られてきたoauth_verifier
- type
- 'authorize'
- set
- レスポンス
- oauth_token
- さっきランダム生成したoauth_token
- oauth_token_secret
- さっきランダム生成したoauth_token_secret
- oauth_token
コンシューマが受け取るパラメータはこんな感じ。
レスポンスボディをparse_strした結果。
Array ( [oauth_token] => DnWFL4DZhGrk82hDPiplfaq0XLtvyllXfuUv9G4DSmQtW1 [oauth_token_secret] => 2m26aQDyGNvufC5i4p4hEod1B9McmcnMEGSU4KkG4tKJmkO4krgU3hrUjjXS7Ag )
保護されたリソースを返す
コンシューマはこの後、RESTful APIを叩く。
- さっき受け取ったoauth_tokenとoauth_token_secretでOAuth認証
- リソースを返す
以上!
アクセストークンは、とりあえず300秒有効って事にしてる。
サブドメインでセッションIDを共有してしまっていた
サブドメインでドメインを分けて、それぞれコンシューマ役とサービスプロバイダ役に見立ててやってみた。
どうやらセッションIDを共有しているらしく、別の環境とは言いがたい。
で、セッションIDを分けてみた。
問題については、↓ここが解りやすい。
セッション値漏洩 : アシアルブログ
http://blog.asial.co.jp/173
VirtualHostごとにセッションIDを分ける方法
httpd.confの
php_value session.cookie_domain xxx.jp
…と思ったら、違う、IEの仕様(バグ)?
結果からいうと、1行追記する事で返ってくるヘッダーは変わるものの、どちらにしろ挙動は変わらなかった。
FirefoxとOperaだと、サブドメインでは分けてくれる。
IE(Sleipnir)だと、sub.xxx.jpに行ってからxxx.jpにすると分けてくれて、xxx.jpに行ってからsub.xxx.jpに行くと共有してしまう。
IEは、デフォルトでCookieはxxx.jpとそのサブドメインまで有効、という認識らしい。
short_open_tag
前にPHPのバージョンを5.3.0にアップデートした時に、↓こう書けなくなったって書いたけど、どうやらphp.iniのshort_open_tagで変えられるらしい。
未確認。
<?php $user = "ゲスト"; ?> こんにちは!<?=$user;?>さん