post のデータに予期しない値が混じっているとセキュリティ上よくないです。悪意ある攻撃者がフォームに存在しないフィールドを予想して、意図しない DB テーブルのカラムを書き換える、ということがおきるかもしれません。
パラメータ改ざん対策が必要です。
そこで、入力フォームで指定したフィールドのみを確実に受け付けるようにする方法を考えました。
考えた方法
- 入力フォームのフィールドをコントローラーやモデルなどサーバサイドで取り出して新しい変数に入れる。
例です。
app/Controller/UsersController.php
<?php App::uses('AppController', 'Controller'); /** * Users Controller * * @property User $User */ class UsersController extends AppController { /** * edit method * * @throws NotFoundException * @param string $id * @return void */ public function edit($id = null) { $this->User->id = $id; if (!$this->User->exists()) { throw new NotFoundException(__('Invalid user')); } if ($this->request->is('post') || $this->request->is('put')) { // 入力フォームの値のみを保存するため、それら以外の post データを排除する。 $save_data['User']['id'] = $this->request->data['User']['id']; $save_data['User']['username'] = $this->request->data['User']['username']; $save_data['User']['password'] = $this->request->data['User']['password']; $save_data['User']['group_id'] = $this->request->data['User']['group_id']; $save_data['Profile']['id'] = $this->request->data['Profile']['id']; $save_data['Profile']['catch_phrase'] = $this->request->data['Profile']['catch_phrase']; $save_data['Profile']['self_introduction'] = $this->request->data['Profile']['self_introduction']; $save_data['Profile']['ExProfile']['id'] = $this->request->data['Profile']['ExProfile']['id']; $save_data['Profile']['ExProfile']['job'] = $this->request->data['Profile']['ExProfile']['job']; if ($this->User->saveAll($save_data, array('deep' => true))) { $this->Session->setFlash(__('The user has been saved')); $this->redirect(array('action' => 'index')); } else { $this->Session->setFlash(__('The user could not be saved. Please, try again.')); } /* */ } else { $this->User->recursive = 2; $this->request->data = $this->User->read(null, $id); } $groups = $this->User->Group->find('list'); $this->set(compact('groups')); } }
行っていることは単純で、フォームのフィールドと同じフィールド名で新しく配列の変数を作って、 post のフィールドデータを入れているだけです。
コントローラーで行っていますが、本当はモデルで行うべき処理だと思います。
app/View/Users/edit.ctp
<div class="users form"> <?php echo $this->Form->create('User'); ?> <fieldset> <legend><?php echo __('Edit User'); ?></legend> <?php echo $this->Form->input('User.id'); echo $this->Form->input('User.username'); echo $this->Form->input('User.password'); echo $this->Form->input('User.group_id'); echo $this->Form->input('Profile.id'); echo $this->Form->input('Profile.catch_phrase'); echo $this->Form->input('Profile.self_introduction'); echo $this->Form->input('Profile.ExProfile.id'); echo $this->Form->input('Profile.ExProfile.job'); echo $this->Form->input('Profile.ExProfile.address'); ?> </fieldset> <?php echo $this->Form->end(__('Submit')); ?> </div>
特筆する点はありません。
おわりに
Security コンポーネントを使っていれば、この仕組みは自動で組み込まれています。「Form tampering protection」です。
また、こちらのページもすばらしいです。CakePHP1.3 の情報ですけれども、Security コンポーネント、パラメータ改ざん対策についての理解が深まりました。ありがとうございます。