事情がありCakePHPでBASIC認証に挑戦。ところがPHPもCakePHPもあまり詳しくなく、さらにネット転がっている情報のほとんどがCakePHP1の情報で動くまで大変苦労しました。その試行錯誤の結果を記しておきます。
まず、データベースにテーブルを作成します。今回は、usersテーブルにusernameとpasswordフィールドを作成します。これが規約だそうです。もちろん別の名前をつけても問題ありませんが、後から設定が必要になります。特にこだわりがないのであれば、下記のようにすると手間が省けるでしょう。
CREATE TABLE IF NOT EXISTS users ( id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, username VARCHAR(50), password VARCHAR(50), created DATETIME DEFAULT NULL, modified DATETIME DEFAULT NULL );
次にモデルの作成。
// /app/Model/User.php <?php App::uses('AuthComponent', 'Controller/Component'); class User extends AppModel { public function beforeSave($options = array()) { $this->data['User']['password'] = AuthComponent::password($this->data['User']['password']); return true; } }
beforeSave()の処理は、cake2から必要になった処理のよう。今回はBASIC認証なので問題ないが、digest認証を利用する場合には、処理が異なる。公式を参考に。
AuthComponentを呼び出すために、二行目が必要だった。本家の解説になくてしばらく悩んだ。
次にAppControllerの作成。
// /app/Controller/AppController.php <?php class AppController extends Controller { var $components = array('Session', 'Auth' => array('authenticate' => array('Basic'))); function beforeFilter(){ $this->Auth->loginAction = array('controller' => 'users', 'action' => 'login', 'admin' => true); $this->Auth->loginRedirect = array('controller' => 'applies', 'action' => 'index', 'admin' => true); $this->Auth->logoutRedirect = $this->webroot; } }
今回はBASIC認証を利用するので、componentsに'Basic'を指定。その他の認証方式を利用するには適切に変更すること。今回は、usersテーブルでusername, passwordを利用するので問題ないが、別のフィールド名を利用している場合には、別途指定が必要。本家を参考のこと。
次にログイン処理を行うコントローラーを作成
// /app/Controller/UsersController.php <?php class UsersController extends AppController { public $name; public $scaffold = "admin"; public function admin_login() { $this->login(); } public function admin_logout() { $this->logout(); } public function login() { if ($this->Auth->login()) { return $this->redirect($this->Auth->redirect()); } else { $this->Session->setFlash(__('Username or password is incorrect'), 'default', array(), 'auth'); } } // ログアウト処理 public function logout() { $this->Auth->logout(); } }
$scaffold = "admin"; としているのは、scaffoldを利用して、CRUD処理の作成を省くため&usersコントローラー全体を {webroot}/admin/users というアドレスにしたいため。そうしたため、 admin_login() という login() の alias を作成した。login() と logout() は、本家のコードそのまま。BASIC認証は logout ができないため、logout処理は必要ない気がするが、とりあえず書いておく。
最後に空ファイルでいいので、 /app/View/Users/admin_login.ctp, /app/View/Users/admin_logout.ctp を作成すること。
これで全てのコントローラーに対してログイン処理が必要になりました。ユーザーを追加して、試してみてください。このコントローラーのこのアクションだけ認証かけたくないという場合には、コントローラー毎に下記のような処理を追加してください。
function beforeFilter(){ $this->Auth->allow('calendar', 'list'); // action_nameを指定 }
BASIC認証なので、ログインフォームを書かなくていいのは大変便利ですが、セキュリティは皆無に近いでしょう。セキュリティに配慮する方は、せめてdigest認証を利用しましょう。もちろんこれも万全ではないことを指摘しておきます。
参考