CakePHP Auth Componentの暗号化を無視する方法

2009.04.16    CakePHP, 渡辺      peter   

WEBシステムを構築する際に必ず構築するログイン処理、CakePHPでは

Auth Componentと呼ばれる便利なControllerコンポーネントが存在します。

これを使うと、特にコードを書くことなく

ログイン処理、ログアウト処理、ユーザ作成・編集時のパスワードハッシュ化を実現できます。

私は説明が下手なので、要点をうまくまとめているサイトをご紹介します。

http://blog.ne2ma2.com/archives/161

暗号化の部分はModelやControllerの部分に戻ってくる時点で行われているため、

CakePHPのバリデーションを使うことができません。

ユーザの編集時にパスワードが勝手に二重でハッシュ化され、以後ログインできなくなったり、

パスワードを必ず入力してもらうことになります。

上記サイトでは異なるモデルでバリデーションを定義することでこれを解決していますが、

もう1つ単純なやりかたとして、暗号化の部分を手動で行う、があります。

Authコンポーネントのファイルのstartup()という関数の中で必ず呼ばれている

$this->data = $controller->data = $this->hashPasswords($controller->data);

をコメントアウトするだけです。

後は、ハッシュ化が必要なときに適時上記と同じ関数をコントローラーで呼ぶだけです。

例: $this->data = $this->Auth->hashPasswords($this->data); //ユーザの入力したパスワードをハッシュ化

あと、ログイン時に入力されたユーザ名とパスワードをハッシュ化して認証する都合上、

Authコンポーネントのログイン関数にも手動で暗号化処理を加えてあげる必要があります。

if (empty($data)) {
$data = $this->data;
}
else{
$data[$this->userModel.".".$this->fields['password']] = $this->password($data[$this->userModel.".".$this->fields['password']]);
}

人様に用意して頂いたものにケチをつけるのは好きではありませんが、

システムの動きとして自然な気がします。

EthnaのimportFormの強化版

2009.04.15    Ethna, PHP, Web, 馬場      baba   

EthnaのAppObject::importForm()は便利ですが、DBの全カラムと同じ名前のform値を取得してしまうため、たとえばzipcodeはハイフン前後で2つのFormを用意して結合した値をセットする、等の処理が少々やりにくいです。
また、どの値がインポートされるのか見えにくいのが何となく気持ち悪い、という人もいると思います。

そこで、AppObjectに下記のようなメソッドを作ってみました。
実際には全AppObjectの基底クラスにすると良いと思います。

class AppId_Hoge extends Ethna_AppObject
{
  function setAll($list, $option = null)
  {
    foreach ($list as $key => $data) {
      $name = ”;
      $value = ”;
      if (is_int($key)) {
        //連想配列のキーが数値の場合は、連想配列の値と同名のform値をセットする
        $name = $data;
        $value = $this->af->get($data);

        //値がNULLの場合、オプション指定によって、無視するか空文字列に変換するかを決定する
        if (is_null($value)) {
          if ($option == OBJECT_IMPORT_IGNORE_NULL) {
            //NULLを無視
            continue;
          } else {
            $value = ”;
          }
        }
      } else {
        //それ以外の場合、連想配列のキーがそのまま名前に、連想配列の値がそのまま設定すべき値になる
        $name = $key;
        $value = $data;
      }

      if (isset($this->prop_def[$name]) == false) {
        Ethna::raiseError(”Unknown property $name”);
        return null;
      }
      $this->set($name, $value);
    }
  }
}

使うときは

$list = array(
  ’user_name’,
  ’password’,
  ’zipcode’ => $this->af->get(’zipcode1′).$this->af->get(’zipcode2′)
);
$obj =& $this->backend->getObject(’Hoge’);
$obj->setAll($list);

のようにすると、単純に配列指定したuser_nameとpasswordはForm値が直接セットされ、連想配列になっているzipcodeは、$list['zipcode']の値がセットされます。
これによって、ほとんどの値はActionFormからそのままセットするが、任意のフィールドだけを特別な値にする、といった処理が簡単になります。

Ethnaでレイアウト

    Ethna, PHP, Web, 馬場   タグ: —    baba   

割と既出ネタですが。。。

Ethnaでも、CakePHPなどのようなレイアウトテンプレートを使いたくなります。
ViewClassのforwardを変更すると、意外と簡単に実現できました。
Controllerの$directoryに’layout’のパスをセットして、ViewClassのforwardを下記のようにオーバーライドします。

class AppId_ViewClass extends Ethna_ViewClass
{
function forward()
{
//Rendererを取得
$renderer =& $this->_getRenderer();
$this->_setDefault($renderer);

//各Viewのコンテンツを取得
$contents = $renderer->perform($this->forward_path, true);


//レイアウトを取得
$layout = $renderer->getProp(’layout_file’);
if ($layout) {
$controller =& $this->backend->getController();
$dir = $controller->getDirectory(’layout’);
$layout_file = $controller->getDirectory(’layout’) . ‘/’ . $layout . ‘.’ . $controller->getExt(’tpl’);
$renderer->setProp(’contents’, $contents);
$renderer->perform($layout_file);
} else {
echo $contents;
}
}

これで、各tplで
{assign var=”layout_file” value=”default”}
と指定すれば、default.tplが呼ばれて、default.tpl内の {$contents} のところに各Viewのコンテンツが挿入されます。

レイアウトファイルに各Viewのテンプレート内から値を渡したいときは、{assign}を使えばOKです。
tplの見通しが良くなって、便利ですよ。

COPYRIGHT [C] 2009 BEYOND PERSPECTIVE SOLUTIONS LTD. ALL RIGHTS RESERVED.