CakePHP2アプリにBASIC認証を追加してみよう

CakePHP2アプリにBASIC認証を追加してみましょう。CakePHP2.4より前のバージョンではBASIC認証を使うにしてもセッション情報が必要になっていてうまく動作しないところがありました。CakePHP2.4.1で試したところ、良さそうなので紹介をします。BASIC認証を使う場合はHTTPSを前提とする必要があるため採用されないことも多いようですが、Webの世界では標準的な認証技術ですから無視をするというわけにもいきませんし、RESTアプリを作成したときにWebクライアントが簡単にWebアプリへアクセスするための認証方式として採用したいと思うことはあるはずです。ということで対応できるようになっておいた方がいいでしょう。

本家の資料は下記になります。ここに記載されている内容を理解すればできますが、フォームによる認証方法の説明が基本となっています。BASIC認証の説明もありますが、わかっている人向けの内容なので、少し難しいでしょう。

こちらではもう少し具体的に手順とコードを示しながら説明をしてみます。まず、ユーザ情報を管理するアプリは「CentOS6でCakePHP2アプリを動かしてみよう | hiro345」を参考にして用意してください。

作成するアプリでは、認証されたユーザだけがユーザ情報を編集できるようにします。また、作成済みのユーザ情報を管理するアプリはbakeコマンドで自動生成しただけなので、パスワードを登録するとDBに平文で保存されてしまいます。今回は、これについても対応をします。ユーザの登録方法についてはいろいろ方法がありますが、今回はユーザ自身がユーザ登録できるようにします。

画面構成は下記のようになります。

トップページ
 +- ユーザ情報一覧*
 +- ユーザ情報登録
 +- ユーザ情報編集*
 +- ユーザ情報削除*

ここで、*がついている画面についてはBASIC認証をかけます。

では、早速 app/Controller/AppController.php でBASIC認証を使うという指定をしましょう。$componentsにSession, Authのコンポーネントを指定します。認証タイプを今回はBASIC認証とするのでAuthのauthenticateへBASICを指定しています。また、ここでは認証にセッションは使わないようにして「AuthComponent::$sessionKey = false;」を指定します。なお、CakePHP2.4より前では AuthComponent::$sessionKey に false を設定するとエラーが発生してうまく動作しませんから注意してください。今回はCakePHP2.4.1を使っていますから大丈夫です。

class AppController extends Controller {
    public $components = array('Session',
          'Auth' => array(
              'authenticate' => array('Basic'),
            )
        );

    public function beforeFilter() {
        parent::beforeFilter();
        AuthComponent::$sessionKey = false;
    }
}

これで、http://localhost/cakephp2_apps/user_app/ 全体にBASIC認証がかかります。ユーザ登録をしていないと、どの画面も見えなくなりました。最初にユーザ登録画面の認証を解除してもいいのですが、ユーザ登録機能でパスワードが平文で保存されるところを先に解決しておきましょう。

ユーザを登録する前にパスワードのハッシュ化をするには、app/Model/User.phpでbeforeSaveメソッドをオーバーライドします。最後の「}」の直前に挿入すれば良いでしょう。AuthComponent::passwordを使うことでパスワードがハッシュ化されます。ここではAuthComponentクラスが提供するデフォルトのハッシュ方法を用いていますが別のアルゴリズムを採用したり、カスタムコンポーネントを独自に作成して利用することもできます。

//略
class User extends AppModel
{
//略
  public function beforeSave($options = array()) {
    if (isset($this->data[$this->alias]['password'])) {
      $this->data[$this->alias]['password'] = AuthComponent::password($this->data[$this->alias]['password']);
    }
    return true;
  }
}

これでハッシュ化されたパスワードで保存がされるようになったのでユーザ情報を安心して登録できます。

ユーザ登録の準備ができたので、ユーザ情報登録画面についてBASIC認証をはずしてみましょう。app/Controller/UsersController.phpでbeforeFilterメソッドをオーバーライドします。「public $components = array(‘Paginator’);」の後にbeforeFilterメソッドを挿入すればいいでしょう。このメソッド内で「$this->Auth->allow(‘add’);」とすることで、UsersControllerのaddメソッドは認証がなくても実行できるようになりました。これにより、ユーザ情報登録画面を表示できるようになります。

// 略
class UsersController extends AppController
{
// 略
  public $components = array('Paginator');

  public function beforeFilter()
  {
    parent::beforeFilter();
    $this->Auth->allow('add');
  }
// 略
}

コードを追加して保存できたら、認証がはずれていることを確認しましょう。

http://localhost/cakephp2_apps/user_app/users/ にアクセスするとBASIC認証ダイアログがでますが、http://localhost/cakephp2_apps/user_app/users/add にアクセスするとBASIC認証ダイアログはでなくなっているはずです。

なお、認証解除のメソッドを複数指定することもできます。その場合は、「$this->Auth->allow(‘add’, ‘edit’);」のようにします。なお、メソッドを使わせたくないことを明示的に指定したい場合は「$this->Auth->deny(‘delete’);」のようにAuthコンポーネントのdenyメソッドを使います。

次にトップページの認証を解除します。もともと用意されている画面はいろいろな機能を使っていて認証が通らないとうまく動作しないコードも含まれているようで、手元で運用モードにしたところ(debugを0にしたところ)、BASIC認証ダイアログが表示される前にエラーとなってしまったからです。トップページをシンプルな画面にするためには app/Config/routes.php を修正して下記のようにします。

略
	//Router::connect('/', array('controller' => 'pages', 'action' => 'display', 'home'));
	Router::connect('/', array('controller' => 'pages', 'action' => 'display', 'simple'));
略

これで、Pagesのhome.ctpではなくsimple.ctpを表示するという指定となります。

次にapp/View/Pages/simple.ctpを用意します。ユーザ登録はユーザ自身ができるようにしたので、リンクを用意しておきます。

<a href="./users/add">ユーザ登録</a>

これでトップページを変更する準備ができました。

トップページについてBASIC認証をはずしてみましょう。UsersController.phpと同様にします。app/Controller/PagesController.phpでbeforeFilterメソッドをオーバーライドします。「public $uses = array();」の後にbeforeFilterメソッドを挿入すればいいでしょう。このメソッド内で「$this->Auth->allow(‘display’);」とすることで、PagesControllerのdisplayメソッドは認証がなくても実行できるようになりました。

// 略
class PagesController extends AppController
{
// 略
  public $uses = array();

  public function beforeFilter()
  {
    parent::beforeFilter();
    $this->Auth->allow('display');
  }
// 略
}

コードを追加して保存できたら、http://localhost/cakephp2_apps/user_app/ へアクセスして認証がはずれていることを確認しましょう。

一方、http://localhost/cakephp2_apps/user_app/users/ へアクセスすると、想定通りにBASIC認証ダイアログがでることがわかります。

それではいよいよユーザを登録しましょう。http://localhost/cakephp2_apps/user_app/users/addへアクセスをして、必要な情報を入力して「Submit」ボタンをクリックします。登録した後の画面で認証が必要になっているためBASIC認証ダイアログがでますが、そこへ今登録したユーザ情報を入力するとユーザ一覧画面が表示されます。

念のためDBも確認をしておきましょう。コンソール画面を表示して次のように入力した時に、ユーザ情報が表示されるはずです。

$ echo "select * from users;" |mysql -u user_app -p user_app

ユーザが登録されていない場合は、app/tmp/log/error.log などでエラーが出ていないか確認してみましょう。

最後に運用モードでの動作も確認してみましょう。app/Config/bootstrap.phpの最後に下記を追加します。これで運用モードになります。

Configure::write('debug', 0);

PHP, CakePHPについては下記が参考になります。

同じタグの記事: BASIC
同じタグの記事: CakePHP
同じタグの記事: PHP
同じカテゴリの記事: Program
関連書籍: CakePHP
関連書籍: PHP