カテゴリー
コンピューター

CakePHP2 認証、Auth コンポーネントのサンプルを世界一シンプルを目指して作ります。

2014年10月11日追記

再び勉強してみましたの♪今度は bake を使用してもっと楽にサンプルを作成することができましたわ♪

★認証のお勉強内容

ログインしないとページにアクセスできないようにする、認証機能を勉強します。同時に、認証が不要なページを設ける方法も確かめます。できるだけシンプルな構造でいきます!

では、次のような認証前後でアクセスできるできないページ、を作成してみます。ログイン用のユーザは、1人だけ作ります。

URL はこんな感じです。

  • ログインページ
    • http://localhost/cakesample3/users/login
  • ログイン前後でアクセスできたりできなくなったりするページ
    • http://localhost/cakesample3/apples
    • http://localhost/cakesample3/beets
    • http://localhost/cakesample3/cherries

今回のサンプルを動かすと、ログイン前後でどのページにアクセスできて、どのページにアクセスできないのかをまとめた表です。

ページ ログイン前にアクセスできる ログイン後にアクセスできる
apples ×
beets ×
cherries

★前提・設定

使用 CakePHP バージョン

  • CakePHP 2.2.0

ログイン用ユーザ

CakePHP の認証時に入力する情報を次のようにします。

  • ユーザ名 username
  • パスワード password

データベース設定

ユーザ名などはデータベースに入れるので、その情報を予め決めておきます。

  • データベース種類 MySQL
  • データベースユーザ sampleuser3
  • データベースパスワード samplepassword3
  • データベース名 sampledb3
  • データベースエンコード utf8

★パスワードを自力で作る。

本や、ネットのサンプルではたいていユーザ登録のアクションなどもあわせて紹介されております。が、もっとシンプルに認証前後のページアクセス時の動きを見ることに集中したいので作りません。

ですので、SQL を直接打って、ユーザを登録します。

ここでポイントです。パスワードは、暗号化して登録します。

そのため、ソルト値というものが必要となります。CakePHP のソルト値を設定しているソースはこちらです。

  • /cakesample3/app/Config/core.php
/**
 * A random string used in security hashing methods.
 */
 Configure::write('Security.salt', 'CSyiZD1w0zBtWiunS7WY2ZOyc2BScf2MJW7CBiRF8SoHwrTRu8');

では、実際に暗号化します。まず準備として、コマンドプロンプトを起動したら、PHP へのパスを通します。わたくしの環境は、環境変数に設定していないのでその都度追加です。

cd C:\pleiades\xampp\php
set path=%path%;%cd%

暗号化方式は sha256 ではなく、デフォルトは sha1 です。sha1 を使いましょう。
また、Windows のコマンドプロンプトと、Linux のコマンドでは php コマンドの使い方が若干違うようです。
わたくしの環境は Windows であり、次のようなコマンドとなりました。

php -r "echo hash('sha1','CSyiZD1w0zBtWiunS7WY2ZOyc2BScf2MJW7CBiRF8SoHwrTRu8password');"

hash 関数の第2引数、長い!、がパスワード部分となります。ソルト値の後ろにパスワードを付けた文字列を暗号化します。

できたパスワードはこちらになりました。

f2851182a7e0ac3df147f08446f16d766c8ea44b

これがパスワードですので、直接 SQL でテーブルに挿入します。

INSERT INTO `sampledb3`.`user` (`id`, `username`, `password`, `created`, `modified`) VALUES (NULL, 'username', 'f2851182a7e0ac3df147f08446f16d766c8ea44b', NULL, NULL);

※おまけ Linux ver

Windows と Linux で、php を範囲を指定するクォーテーションが違います。地味にはまりますので注意です。

php -r 'echo(hash("sha1","CSyiZD1w0zBtWiunS7WY2ZOyc2BScf2MJW7CBiRF8SoHwrTRu8password"));'

★ MySQL ソース

準備として、コマンドプロンプトにて MySQL へのパスを通します。

cd C:\pleiades\xampp\mysql\bin
set path=%path%;%cd%

root で MySQL にアクセスして、データベース、ユーザ、を作成します。パスワードを設定します。

GRANT ALL PRIVILEGES ON sampledb3.* TO sampleuser3@localhost IDENTIFIED BY 'samplepassword3';
FLUSH PRIVILEGES;
CREATE DATABASE sampledb3 CHARACTER SET utf8;

続いて、認証用のデータを格納するテーブルを作成します。うっかり MySQL からログアウトし手しまいましたので、mysql -u sampleuser3 -psamplepassword3 sampledb3 のコマンドを打つことで、作ったユーザ、パスワード、データベースにアクセスして作ります。

# ユーザテーブル
CREATE TABLE `user` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `username` varchar(50) NOT NULL,
 `password` varchar(50) NOT NULL,
 `created` datetime DEFAULT NULL,
 `modified` datetime DEFAULT NULL,
 PRIMARY KEY (`id`)
)DEFAULT CHARSET=utf8;

★CakePHP ソース一覧

認証

■モデル

  • /cakesample3/app/Model/User.php

■コントローラ

  • /cakesample3/app/Controller/AppController.php
  • /cakesample3/app/Controller/UsersController.php

■ビュー

  • /cakesample3/app/View/Users/login.ctp

表示するだけのページ

■モデル

  • なし

■コントローラ

  • /cakesample3/app/Controller/ApplesController.php
  • /cakesample3/app/Controller/BeetsController.php
  • /cakesample3/app/Controller/CherriesController.php

■ビュー

  • /cakesample3/app/View/Apples/index.ctp
  • /cakesample3/app/View/Beets/index.ctp
  • /cakesample3/app/View/Cherries/index.ctp

■エレメント

  • /cakesample3/app/View/Elements/all_links.ctp

★ソース詳細

認証

■モデル

  • /cakesample3/app/Model/User.php
<?php
App::uses('AppModel', 'Model');
/**
 * User Model
 *
 */
class User extends AppModel {

/**
 * Use table
 *
 * @var mixed False or table name
 */
	public $useTable = 'user';

}

■コントローラ

既存のソースにハイライト部分を追加します。

  • /cakesample3/app/Controller/AppController.php
<?php
/**
 * Application level Controller
 *
 * This file is application-wide controller file. You can put all
 * application-wide controller-related methods here.
 *
 * PHP 5
 *
 * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
 * Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
 *
 * Licensed under The MIT License
 * Redistributions of files must retain the above copyright notice.
 *
 * @copyright     Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
 * @link          http://cakephp.org CakePHP(tm) Project
 * @package       app.Controller
 * @since         CakePHP(tm) v 0.2.9
 * @license       MIT License (http://www.opensource.org/licenses/mit-license.php)
 */

App::uses('Controller', 'Controller');

/**
 * Application Controller
 *
 * Add your application-wide methods in the class below, your controllers
 * will inherit them.
 *
 * @package       app.Controller
 * @link http://book.cakephp.org/2.0/en/controllers.html#the-app-controller
 */
class AppController extends Controller {

/**
 * Array containing the names of components this controller uses. Component names
 * should not contain the "Component" portion of the classname.
 *
 * @var array
 */
	public $components = array(
			// Auth
			'Auth' => array(
					'loginRedirect' => array('controller' => 'apples', 'action' => 'index'),
					'logoutRedirect' => array('controller' => 'users', 'action' => 'login'),
					'authError' => 'このページを表示するには、ログインを行ってください。',
					'authenticate' => array(
							'all' => array(
									'fields' => array(
											'username' => 'username',
											'password' => 'password',
									),
							),
							'Form',
					),
			),
			// セッション
			'Session',
	);
}
  • /cakesample3/app/Controller/UsersController.php
<?php
App::uses('AppController', 'Controller');
/**
 * Users Controller
 *
 * @property User $User
 */
class UsersController extends AppController {

/**
 * Called before the controller action.  You can use this method to configure and customize components
 * or perform logic that needs to happen before each controller action.
 *
 * @return void
 */
	public function beforeFilter() {
		// ログインなしでアクセス可能なページ(このコントローラーのアクション)を列挙
		$this->Auth->allow('logout');
	}

/**
 * ログイン処理
 */
	public function login() {
		// フォームに入力があった場合のみログイン処理を行い、ダッシュボードへ移動
		if ($this->request->is('post')) {
			if ($this->Auth->login()) {
				$this->redirect(array('controller' => 'apples', 'action' => 'index'));
			} else {
				$this->Session->setFlash(__('ユーザ名またはパスワードが誤っています。再度入力してください。'));
			}
		}
	}

/**
 * ログアウト処理
 */
	public function logout() {
		$this->redirect($this->Auth->logout());
	}

}

■ビュー

  • /cakesample3/app/View/Users/login.ctp
<h2>Users login ビュー</h2>
<div class="users form">
	<?php echo $this->Session->flash('auth'); ?>
	<?php echo $this->Form->create('User');?>
	<fieldset>
		<legend>
			<?php echo __('ユーザ名とパスワードを入力してください。'); ?>
		</legend>
		<?php
		echo $this->Form->input('username');
		echo $this->Form->input('password');
		?>
	</fieldset>
	<?php echo $this->Form->end(__('ログイン'));?>
</div>
<?php echo $this->element('all_links'); ?>

表示するだけのページ

■モデル

  • なし

■コントローラ

クラス名、ファイル名以外は全部同じです。なので最初の ApplesController.php のみ掲載します。

  • /cakesample3/app/Controller/ApplesController.php
  • /cakesample3/app/Controller/BeetsController.php
  • /cakesample3/app/Controller/CherriesController.php
<?php
/**
 * Apples Controller
 *
 * @property Apple $Apple
 */
class ApplesController extends AppController {

/**
 * index method
 *
 * @return void
 */
	public function index() {
	}

}
?>

■ビュー

こちらも、コントローラーと同様、ほぼ同じですので Apples 以外のビューは省略します。

  • /cakesample3/app/View/Apples/index.ctp
  • /cakesample3/app/View/Beets/index.ctp
  • /cakesample3/app/View/Cherries/index.ctp
<h2>Apples ビュー</h2>
<?php echo $this->element('all_links'); ?>

■エレメント

  • /cakesample3/app/View/Elements/all_links.ctp
<div class="actions">
	<h3>リンク</h3>
	<ul>
		<?php
		echo "<li>" . $this->Html->link('ログイン', array('controller' => 'users', 'action' => 'login')) . "</li>";
		echo "<li>" . $this->Html->link('ログアウト', array('controller' => 'users', 'action' => 'logout')) . "</li>";
		echo "<li>" . $this->Html->link('Apples', array('controller' => 'apples', 'action' => 'index')) . "</li>";
		echo "<li>" . $this->Html->link('Beets', array('controller' => 'beets', 'action' => 'index')) . "</li>";
		echo "<li>" . $this->Html->link('Cherries', array('controller' => 'cherries', 'action' => 'index')) . "</li>";
		?>
	</ul>
</div>

★おわりに

パスワード生成のために Windows コマンドプロンプトで PHP を実行するときに役に立ったページです。ありがとうございます!

「CakePHP2 認証、Auth コンポーネントのサンプルを世界一シンプルを目指して作ります。」への5件の返信

コメントを残す