データのサニタイジング(2-2) 検索画面の作成

サニタイズ済みで登録したデータ取り扱いの、もう一つの問題点。
検索時に、htmlエンティティ済みの値をセットする方法。


controllerで絞込条件をセットする段階で、htmlエンティティ化して登録したfiledごとに、逐次エンティティ化する方が良いようです。
modelのbeforeFindの$queryDataでは、fieldの区別がもうつきません。


管理側のUsers一覧表示画面に、Usersをname(名前)で検索する機能を追加。
作成は、以下を参考にContainableビヘイビア使用*1
http://fresh.pure-white.jp/cakephp/23paginate
http://book.cakephp.org/ja/view/165/Controller-Setup


$nameの入力をサニタイズしてSQLにセットしている箇所は以下。
Index: controllers/users_controller.php

+    $contain["User.name LIKE"] = "%".Sanitize::html($name)."%";
(中略)
+$this->set('users', $this->paginate('User', $contain));


SQLインジェクション対策は、暗黙的に実行されるようなので、htmlエンティティのみ処理しています。*2

  • 入力値にhtml()処理を行なわない状態で 「';」を入力して検索した時の実行SQL*3

SELECT `User`.`id`, `User`.`group_id`, `User`.`name`, `User`.`username`, `User`.`password`, `User`.`created`, `User`.`modified` FROM `users` AS `User` WHERE `User`.`name` LIKE '\';' LIMIT 20

その他の処理も含めた全差分。
Index: models/user.php

        var $name = 'User';
        var $belongsTo = array('Group');
        var $actsAs = array(
               'Acl' => 'requester',
+               'Containable',
        );

Index: controllers/users_controller.php

        function admin_listview() {
-               self::_listview();
+               // 検索処理
+               $this->User->contain();
+               $contain = array();
+               $searchword = array();
+               if (!empty($this->data)) {
+                       if (isset($this->data['User']['name'])) {
+                               $name = $this->data['User']['name'];
+                       }
+               } else {
+                       if (isset($this->passedArgs['name'])) {
+                               $name = urldecode($this->passedArgs['name']);
+                       }
+               }
+
+               if (isset($name)) {
+                       $contain["User.name LIKE"] = "%".Sanitize::html($name)."%";
+
+                       $this->data['User']['name'] = $name;
+                       $searchword['name'] = urlencode($name);
+               }
+               $this->set('searchword', $searchword);
+
+               $this->set('users', $this->paginate('User', $contain));
+
        }


views/users/admin_listview.ctp*4

+<h4><?php //todo:toggle echo $html->link(__('Search Users', true)); ?></h4>
+<fieldset class="searchFieldset" id="adminSearchFieldset">
+<legend><?php __('Search User');?></legend>
+<div class="search form">
+<?php echo $form->create('User', array('action' => 'listview', 'type' => 'post')); ?>
+<?php echo $form->input('name'); ?>
+<?php echo $form->end('Search'); ?>
+</div>
+<?php $paginator->options(array('url' => $searchword)); ?>
+</fieldset>

*1:現段階では、Containableする必要は特にありませんが、将来的にUsersに紐づくデータが増えた時に備えて

*2:具体的な処理箇所は不明…

*3:デバッグ画面より

*4:デザインは別修正予定