タイトルの通りに驚きました。
.htaccess でベーシック認証をかけていたら、うまくいかなくて、「CakePHPでできたらよくね?」と思い探したらありました!
ありがたやーm(_ _ )m
Basic認証をかけたいControllerのbeforeFilter()に用意すればおk
フローのイメージは、「途中idとパスワードが間違っていたらエラーにする」って感じですね。
<?php public function beforeFilter() { parent::beforeFilter(); //Basic認証 $this->autoRender = false; // id $loginId = 'hoge'; // passwd $loginPassword = 'hogehoge'; if (isset($_SERVER['PHP_AUTH_USER'])) { if (! ($_SERVER['PHP_AUTH_USER'] == $loginId && $_SERVER['PHP_AUTH_PW'] == $loginPassword)) { $this->basicAuthError(); } } else { // 失敗したら途中で処理終了 $this->basicAuthError(); } $this->autoRender = true; } 〜 省略 〜 private function basicAuthError() { header('WWW-Authenticate: Basic realm="Please enter your ID and password"'); header('HTTP/1.0 401 Unauthorized'); die("Invalid id / password combination. Please try again"); }
自分はコンポーネントにして実装しました。
よかった。うまくいったわ
疑問が2つ
このソースだけみると疑問が2つ
- どーして $_SERVER で、条件を判定するのか。
- どーして $this->autRender をfalseにしなければならないのか。
せっかくなので調べてみる。
$_SERVER を調べる
ログに出力してみると、中身がこんな感じでした。
2015-05-01 11:48:40 Error: Array ( [REDIRECT_STATUS] => 200 [HTTP_HOST] => localhost [HTTP_CONNECTION] => keep-alive [HTTP_CACHE_CONTROL] => max-age=0 [HTTP_ACCEPT] => text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 [HTTP_USER_AGENT] => Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 [HTTP_REFERER] => http://localhost/ [HTTP_ACCEPT_ENCODING] => gzip, deflate, sdch [HTTP_ACCEPT_LANGUAGE] => ja,en-US;q=0.8,en;q=0.6 [HTTP_COOKIE] => CAKEPHP=619pd9buil7r1mdelgluegivf5 [PATH] => /usr/bin:/bin:/usr/sbin:/sbin [SERVER_SIGNATURE] => [SERVER_SOFTWARE] => Apache [SERVER_NAME] => localhost [SERVER_ADDR] => ::1 [SERVER_PORT] => 10082 [REMOTE_ADDR] => ::1 [DOCUMENT_ROOT] => /Users/user/cakephp [REQUEST_SCHEME] => http [CONTEXT_PREFIX] => [CONTEXT_DOCUMENT_ROOT] => /Users/user/cakephp [SERVER_ADMIN] => you@example.com [SCRIPT_FILENAME] => /Users/user/cakephp/app/webroot/index.php [REMOTE_PORT] => 58849 [REDIRECT_URL] => / [GATEWAY_INTERFACE] => CGI/1.1 [SERVER_PROTOCOL] => HTTP/1.1 [REQUEST_METHOD] => GET [QUERY_STRING] => [REQUEST_URI] => / [SCRIPT_NAME] => /app/webroot/index.php [PHP_SELF] => /app/webroot/index.php [PHP_AUTH_USER] => hoge // これがid [PHP_AUTH_PW] => hogehoge // これがパスワード [REQUEST_TIME_FLOAT] => 1430966920.197 [REQUEST_TIME] => 1430966920 )
なるほど、サーバのグローバル変数で管理すればどこでも参照が可能になるからかな。
ということでひとつ実験。全部リフレッシュするとログインできなくなるよね。
<?php 〜 省略 〜 $loginPassword = 'hogehoge'; // 空っぽにする $_SERVER = array(); if (isset($_SERVER['PHP_AUTH_USER'])) { if (! ($_SERVER['PHP_AUTH_USER'] == $loginId && $_SERVER['PHP_AUTH_PW'] == $loginPassword)) { $this->basicAuthError(); } } else { 〜 省略 〜
予想通り、再認証が必要になったった。
$this->autoRender を調べる
autoRender は、Viewを利用するかをしないかを決めるプロパティだ。
この辺でピンときました。
Basic認証は認証するidとパスワードを入力してもらう際、小さなポップアップみたいなブロックがでてきますが、その際にViewを使用しないようにfalseを使っていると思います。
では、実験。Basic認証前にfalseにしたautoRenderの記述を削除します。
<?php 〜 省略 〜 public function beforeFilter() { parent::beforeFilter(); //Basic認証 // $this->autoRender = false; コメントアウト 〜 省略 〜
何も起こりませんでした(´・ω・)
普通に認証できましたね。なんでだろう?
とりあえず、ちょっとした疑問が無くなったので(新しい疑問は浮かびましたが)良しとします。
※この記事書いている時に見つけましたが、もう少し簡単な方法がある。今度はそれをブログに乗っけます。