CakePHP で OAuth 認証をしてログインなどをしたり、会員データをデータベースに持っておく仕組みを作る際のサンプルを紹介します。CakePHP 1.3 での動作確認をしています。今後出てくる CakePHP 2.x 系では動作確認しておりませんのでご了承ください。
- cakephp用OAuth認証ライブラリをつかってみた – メガネ女子(21)のメモブログ
- TwitterのOauthを使ってCakePHPのAuthコンポーネントにログインさせる – kur.jp
- CakePHPでTwitterマッシュアップを作る#4 – BUENA VISTA SOCIAL BLOG
OAuth 認証ライブラリを組み込み
以下のページより OAuth のライブラリを読み込みます。
OAuth consumers for CakePHP – by cakebaker
このファイルを vender/ に入れます。
OAuth 認証できる会員ログインするコントローラーとモデル
完成形を公開しておきます。いろいろと最低限動くようにするとこのような感じでしょうか。このコントローラーとモデルを使うとできることを下に箇条書きにしておきます。
- Twitter のアカウントでログインをすることができる。
- 初回のログインでは新規アカウント登録がされる、すでにアカウントがある場合はアカウントのログイン時間やトークン、ユーザー名などが最新の状態に更新される。
- ログインの認証や保持は Auth コンポーネントを使っておりうまい具合に OAuth と連携している。
コントローラー
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 | <?php App::import('Vendor', 'oauth', array('file' => 'OAuth/oauth_consumer.php')); class MemberController extends AppController { public $name = 'Member', $components = array('Auth'); function beforeFilter() { $this->Auth->userModel = 'Member'; $this->Auth->allow('index', 'login', 'twitter', 'twitter_callback'); $this->Auth->fields = array('username' => 'access_token_key', 'password' => 'access_token_secret'); $this->Auth->loginAction = '/member/'; parent::beforeFilter(); } public function index() { $auth = $this->Session->read('Auth'); if(isset($auth['Member']['user_id'])) { $this->set('title_for_layout', $auth['Member']['user_name'] . 'さんのマイページ'); } else { $this->set('title_for_layout', 'ゲストさんのマイページ'); $this->render('guest_index'); } } public function login() { $auth = $this->Session->read('Auth'); if($auth['Member']['user_id']) { $this->redirect('/member/'); } else { $this->redirect('/member/twitter'); } } public function logout() { $auth = $this->Session->read('Auth'); if($auth['Member']['user_id']) { $this->Auth->logout(); $this->redirect('/member/'); } else { $this->redirect('/member/'); } } public function twitter() { $consumer = $this->createConsumer(); $requestToken = $consumer->getRequestToken('https://twitter.com/oauth/request_token', 'http://hoge.com/member/twitter_callback'); $this->Session->write('twitter_request_token', $requestToken); $this->redirect('https://twitter.com/oauth/authorize?oauth_token=' . $requestToken->key); } public function twitter_callback() { $consumer = $this->createConsumer(); $requestToken = $this->Session->read('twitter_request_token'); $accessToken = $consumer->getAccessToken('https://twitter.com/oauth/access_token', $requestToken); if($accessToken != '') { // Twitter からユーザーデータを取得 $json = $consumer->get($accessToken->key, $accessToken->secret, 'http://twitter.com/account/verify_credentials.json', array()); $twitterData = json_decode($json, true); $consumer->post($accessToken->key, $accessToken->secret, 'http://twitter.com/statuses/update.json', array('status' => '接続しました。')); $this->Member->update( Array( "user_id" => $twitterData['id_str'], "user_name" => $twitterData['screen_name'], "access_token_key" => $accessToken->key, "access_token_secret" => $accessToken->secret, ) ); $user['Member']["access_token_key"] = $accessToken->key; $user['Member']["access_token_secret"] = $accessToken->secret; if ($this->Auth->login($user)) { $this->Session->write('hoge_request_token', $this->getRequestToken()); $this->redirect('/member/'); } $this->render('index'); } else { $this->cakeError('error404'); } } private function getRequestToken() { $auth = $this->Session->read('Auth'); $token = md5($auth['Member']['created'] . $auth['Member']['id'] . 'SixjDklLT5mRuDEgRZPGQxYxpy9kC7iI'); return $token; } private function requestAuth() { $auth = $this->Session->read('Auth'); $tokenAuth = $this->Session->read('hoge_request_token'); $tokenTemp = $this->getRequestToken(); if($tokenAuth == $tokenTemp) { return true; } else { return false; } } } |
モデル
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | <?php class Member extends AppModel { var $name = 'Member'; var $useTable = 'members'; /* * うまい具合にメンバーの登録・更新ができる関数 */ public function update($member_data) { $member = $this->find('first', array('conditions' => array('user_id' => $member_data['user_id']))); if($member) { $member_data['id'] = $member['Member']['id']; } $this->create(); $this->save(Array("Member" => $member_data)); } } |
データベースの会員テーブル
1 2 3 4 5 6 7 8 9 10 11 | CREATE TABLE IF NOT EXISTS `members` ( `id` int(11) NOT NULL AUTO_INCREMENT, `user_id` int(64) NOT NULL, `user_name` varchar(64) NOT NULL, `access_token_key` text NOT NULL, `access_token_secret` text NOT NULL, `created` datetime NOT NULL, `updated` datetime NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `user_id` (`user_id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=4 ; |
本記事のコードは動作を理解した上でご利用ください。またバグやセキュリティホールなど御座いましたら管理者までご連絡ください。
jayHatmakerさんのコメント
コントローラ名ですが、複数形のMembersControllerになるんじゃないかな?
あと、最後のテーブルの「updated」って「modified」じゃない?