CakePHP::obAuthを使ったユーザ認証

7月 2nd, 2007 admin Posted in CakePHP, PHP |

2009/11/11 追記
アクセス有難う御座います。当ページのobAuthを使った認証はCakePHP1.1用のものです。
CakePHP1.2以降では標準の認証コンポーネントを使うことが推奨されており、そちらの方がずっと簡単になっています。
詳しくはCakePHPのマニュアルページをご覧下さい。
http://book.cakephp.org/ja/view/172/Authentication

obAuth Simple Authenticationを使ったユーザ認証を作成しました。

以下の内容はobAuth Component Tutorialの内容のエスパー翻訳+作業ログになっています。

イントロダクション

obAuthはシンプルな認証用のコンポーネントです。下記のような感じで超簡単に権限設定が行えます。
< ?php $this->obAuth->lock(array(1)); ?>
この場合ユーザグループが1のユーザだけがこのアクションを実行できるということになります。簡単でしょう?

なお、このコンポーネントはまだアルファな段階なのでフィードバックとかよろしく!

目次

      コンポーネントのダウンロード
      データベーステーブルの作成
      コンポーネントの設置とモデルの作成
      必要なアクションの設定
      認証の開始
      そのほかTips&Tricks

コンポーネントのダウンロード

コンポーネントをhttp://bakery.cakephp.org/articles/view/130からダウンロードしてください。

お勧めのデータベーステーブル

obAuthではusersとgroupsというテーブルを使用します。
Download code
usersテーブルはid, group_id, username, passwordのカラムさえあればなんでもOKです。

-- --------------------------------------------------------

--
-- Table structure for table `groups`
-- 

CREATE TABLE `groups` (
  `id` int(10) unsigned NOT NULL auto_increment,
  `name` varchar(50) NOT NULL default '',
  `created` datetime NOT NULL default '0000-00-00 00:00:00',
  `modified` datetime NOT NULL default '0000-00-00 00:00:00',
  PRIMARY KEY  (`id`)
) ENGINE=InnoDB DEFAULT;

--
-- Dumping data for table `groups`
-- 

INSERT INTO `groups` (`id`, `name`, `created`, `modified`) VALUES (1, 'Member', '0000-00-00 00:00:00', '0000-00-00 00:00:00');
INSERT INTO `groups` (`id`, `name`, `created`, `modified`) VALUES (2, 'Admin', '0000-00-00 00:00:00', '0000-00-00 00:00:00');

-- --------------------------------------------------------

--
-- Table structure for table `users`
-- 

CREATE TABLE `users` (
  `id` int(10) unsigned NOT NULL auto_increment,
  `username` varchar(50) NOT NULL default '',
  `password` varchar(32) NOT NULL default '',
  `fname` varchar(50) NOT NULL,
  `lname` varchar(50) NOT NULL,
  `email` varchar(100) NOT NULL default '',
  `group_id` int(10) unsigned NOT NULL default '0',
  `active` tinyint(1) unsigned NOT NULL default '0',
  `created` datetime NOT NULL default '0000-00-00 00:00:00',
  `modified` datetime NOT NULL default '0000-00-00 00:00:00',
  PRIMARY KEY  (`id`),
  KEY `group_id` (`group_id`)
) ENGINE=InnoDB DEFAULT;

コンポーネントの設置とモデルの作成

コンポーネントをダウンロードしたら/app/controllers/components/ob_auth.phpって感じで設置してください。
そして、設置が終わったらコントローラーからコンポーネントを呼んでください。この例ではposts_controller.phpを使います。

< ?php
class PostsController extends AppController
{
var $name = ‘Posts’;
var $components = array(”obAuth”);  //この行で呼んでいる
}
?>

次は、UserモデルとGroupモデルのアソシエーションを設定しよう。もしわかってないならhttp://wiki.cakephp.org/docs:understanding_associations
を見るように。(日本語だとhttp://cakephp.jp/doc/ch06s04.html)

2007/07/10追記
/app/models/group.php

class Group extends AppModel {
    var $name = 'Group';
    var $hasMany = array('User' => array(
            'className'	=>    'User'
        )
    );
}

/app/models/user.php

class User extends AppModel {
    var $name = 'User';
    var $belongsTo = array(
            'Group' =>
                array('className' => 'Group',
                        'foreignKey' => 'group_id',
                        'conditions' => '',
                        'fields' => '',
                        'order' => '',
                        'counterCache' => ''
                ),

    );
}

これが終わったら、ついにobAuthが使えるよ!

必要なアクションの設定

obAuth componentを使うには重要なLogin、Logoutアクションが必要だ。
/app/controllers/users_controller.phpを作りましょう

< ?php
class UsersController extends AppController
{
	var $name = "Users";
	var $components = array("obAuth");
	function login()
	{
	    if(isset($this->data['User']))
	    {
	        if($this->obAuth->login($this->data['User']))
	        {
	            $this->redirect('/users');
	        }
	        $this->flash("Username/Password is incorrect","/users/login");
	    }
	}
	function logout()
	{
	    $this->obAuth->lock();
	    $this->obAuth->logout();
	    $this->flash('You are now logged out.');
	    $this->redirect('/');
	}
}
?>

次は、ビューだ。ログアウトはリダイレクトするだけだからログインのやつだけでOK

<?php echo $html->formTag('/users/login')?> 
<fieldset> 

<legend>User Login</legend> 

<label for="username">Username: </label> 

<?php echo $html->input('User/username', array('style' => 'width: 150px'))?><br /> 

<label for="password">Password: </label> 

<?php echo $html->password('User/password', array('style' => 'width: 150px'))?><br /> 

<label for="submit">&nbsp;</label><br /> 

<?php echo $html->submit('Sign In')?>     
</fieldset> 
</form>

認証の開始

PostsコントローラのaddアクションでグループIDが3の人だけ実行できるような認証にするときはこんな感じ

< ?php
function add()
{
    $this->obAuth->lock(array(3)); // Only users with the group_id '3' are allowed here

    if (!empty($this->data))
    {
        if ($this->Post->save($this->data))
        {
            $this->flash('Your post has been saved.','/posts');
        }
    }
}
?>

んで、もしグループIDが2と3の人に許可したいなら

$this->obAuth->lock(array(2,3));

こんな感じに書けます。
グループIDを空にしたときにはすべてのユーザに許可したことになります。

追記
obAuthのチュートリアルにbeforeFilterでの認証方法が書かれていました。

	function beforeFilter(){
		$this->obAuth->startup($this);
		if($this->params['action'] != 'login'){
			$this->obAuth->lock(array(1,2,3));
		}
	}

ビューでの扱い方

CakePHPではビューにコンポーネントは自動的にセットされているようなので

< ?php if(isset($obAuth->User)){ ?>
<li>< ?php echo $html->link("ログアウト","/users/logout"); ?></li>
< ?php } ?>

こんな感じでかける。超簡単です。

要変更

ob_auth.phpの中で$sesskeyが定義されているけど、これは自分用のランダムな値に書き換えておくべきなんだと思う。

追記:2007/07/07
コントローラーで$this->obAuth->login($this->data);とかした直後にgetGroupID()とかが使えなかったので、コンポーネントのログイン処理の最後のところでuserをセットするように変更した。

obAuth#login()

	// Method to check if user is logged.
	function login($data)
	{

		$username = $data["{$this->user_fields['username']}"];
		$password = $data[$this->user_fields['password']];
		$conditions = array($this->user_model.".".$this->user_fields['username'] => $username, $this->user_model.".".$this->user_fields['password'] => md5($password), $this->user_model.".active" => 1);

		$user = $this->controller->{$this->user_model}->find($conditions);

		if (empty($user)) {
			return false;
		} else {
			$sessdata["{$this->user_model}"]['id'] = $user["{$this->user_model}"]["{$this->user_fields['id']}"];
			$sessdata["{$this->user_model}"]['username'] = $user["{$this->user_model}"]["{$this->user_fields['username']}"];
			$sessdata["{$this->user_model}"]['password'] = $user["{$this->user_model}"]["{$this->user_fields['password']}"];
			$sessdata["{$this->group_model}"]['id'] = $user["{$this->group_model}"]["{$this->group_fields['id']}"];
			$sessdata["{$this->group_model}"]['name'] = $user["{$this->group_model}"]["{$this->group_fields['name']}"];
			$sessdata["{$this->user_model}"]['login_hash'] = md5($this->sesskey . $sessdata["{$this->user_model}"]['username'] . $sessdata["{$this->user_model}"]['password'] . $sessdata["{$this->group_model}"]['id']);
			$this->Session->write($this->sesskey, $sessdata);
			$this->user = $this->Session->read($this->sesskey);
			return true;
		}
	}

2007/07/09追記
snapz CakePHP いちばん簡単な認証システムで指摘を受けたので、SQLのコードを記事内に掲載しました。後半の解説が分からないとのことですが・・・ぜひコメント、トラックバックください。

関連するエントリ

5 Responses to “CakePHP::obAuthを使ったユーザ認証”

  1. 素早い対応に驚きました。感謝感激
    解説がわからない なんて書き方は失礼でした。すいません。
    修正しました。

  2. このままだと、
    http://domain.com/blog/delete/3
    とすると削除しちゃうようですね。

  3. このままだと、ログインしなくても
    http://domain.com/blog/delete/3
    とすると削除しちゃうようですね。

  4. XAMPP(PHP5.2.4)で動いていた obAuth ですが
    FreeBSD6.3(PHP5.2.6)で動かしたときに,

    Notice (8): Trying to get property of non-object [APP/controllers/components/ob_auth.php, line 41]

    というエラーに悩まされました.

    現象としては,login()メソッドの

    $user = $this->controller->{$this->user_model}->find($conditions);

    の部分で,$this->controller がなくなっていました.

    困りつつも,いろいろ試行錯誤した結果,php.ini の
    zend.ze1_compatibility_mode = On
    をOffにしたら,startup()で渡したcontrollerをちゃんと保持
    できるようになり,うまく動作しました.

    やっぱり,ちゃんと理解しないで使うと嵌りますね...

  5. [...] http://www.jamboree.jp/cms/archives/10 コメントをどうぞ 返信をキャンセル [...]

Leave a Reply