CakePHPで外部からのデータ改竄を防止する
CakePHPでアプリケーションを作成する場合、注意しておかないと外部から容易にデータを改竄できるアプリケーションができあがってしまいます。この問題はCakePHPガイドブックにも書かれています。
外部からのデータ改竄を防止するには、CakePHPガイドブックの211~212ページに書かれている対策をしておく必要があります。ただし、この方法は値のチェックにempty()を使用しているため、フィールドの値として0を保存することができません。また、空文字とnullを区別したい場合にも対応できません。これらの問題にも対応できるように、ホワイトリストを基にフィルタリングするメソッドをAppModelクラスに追加してみました。
- /app/app_model.php
class AppModel extends Model { // データのフィルタリング処理 function filter($data = null, $whiteList = null) { // データがemptyの場合はdataプロパティを代入 if (empty($data)) { $data = $this->data; } $_data = array(); // ホワイトリストを基にデータを走査 foreach ($whiteList as $model => $fields) { foreach ($fields as $field => $default) { // データが設定されていないか、emptyで0以外の場合はデフォルト値を代入 if (!isset($data[$model][$field]) || (empty($data[$model][$field]) && $data[$model][$field] != '0')) { $_data[$model][$field] = $default; } else { $_data[$model][$field] = $data[$model][$field]; } } } return $_data; } }
実際に使用する場合は、コントローラからvalidates()やsave()の前にデータとホワイトリストの配列を渡して呼び出します。ホワイトリストはモデル名とフィールド名をキーにした二次元配列で、フィールド名とデフォルト値を設定しておきます。
- /app/controllers/posts_controller.php
class PostsController extends AppController { var $name = 'Posts'; // データを追加するためのアクションメソッド function add() { // POSTされたデータがあれば保存処理 if (!empty($this->data)) { // 保存するフィールドのホワイトリスト $whiteList = array( 'Post' => array( 'name' => null, 'description' => null ) ); // ホワイトリストを基にフィルタリング $data = $this->Post->filter($this->data, $whiteList); if ($this->Post->validates($data)) { $this->Post->save($data, false); $this->flash('データが追加されました。', '/posts/'); return; } } } }
ここまで書いた後に、モデルクラスにwhitelistというプロパティがあることに気づきました。情報がないのでよくわかりませんが、単にデータ改竄を防止したいだけの場合には、コントローラのアクションごとにwhitelistプロパティを設定するだけでもよいのかもしれません。
CakePHPは、まだこういう細かい部分でしっくりこないことが多いです。CodeIgniter ユーザガイド 日本語版を見る限りではCodeIgniterのほうが使いやすい気がしてきています。
コメント (2)
やはりそうでしたか。
次回、使うときにはそちらを使ってみようと思います 🙂
トラックバック (0)
この記事へのトラックバックはまだありません。
指摘されている通りwhitelistプロパティとsaveメソッドにwhitelist引数もあります。