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 コンポーネント、パラメータ改ざん対策についての理解が深まりました。ありがとうございます。
