プラグインで管理画面を作る時に、ユーザにフォームに入力してもらったり、セレクトやラジオボタンなどで選択してもらってそれをデータベースに保存する時、色々なセキュリティ上の設定が必要ですが、それらについてメモします。
管理画面の作り方については、@lilyfanjpさんのこの記事にあるPDFが参考になります。
これを見ただけで僕が分からなかった部分については、@MakeGoodTimeさんに教わったりして、理解できましたので、ここで共有させてもらいます。
まずは、セレクトフォームの場合を用意して、のちのち数字、URL、メールアドレス、文字列、日付などを増やしていければと思います。
ここをコピペすれば最低限安心できる感じで。
例のフォーム
例として簡単なフォームを作ります。
</p> <form action="" method="post"> <table> <tr valign="top"> <th scope="row"><label for="xxx">果物</label></th> <td> <select name="fruits" id="fruits"> <?php $select_options = array( array('value' => 'apple', 'text'=>'apple'), array('value' => 'banana', 'text'=>'banana'), array('value' => 'orange', 'text'=>'orange') ); foreach ($select_options as $select_option) : ?></p> <option value="<?php echo esc_attr($select_option['value']); ?>" <?php if(get_option('fruits') == $select_option['value']){ echo ' selected="selected"' } ?>><?php echo esc_attr($select_option['text']); ?></option> <p> <?php endforeach; ?> </select> </td> </tr> </table> <p class="submit"><input type="submit" name="Submit" class="button-primary" value="変更を保存" /></p> <form>
これで、りんご、バナナ、オレンジから一つを選んでもらうフォームができます。actionは空、methodはpostです。htmlタグは、管理画面の他のページに合わせてます。
値を保存する方法
オプションテーブルに値を保存する場合は、セキュリティを無視すると以下。
update_option('fruits', '$_POST['fruits']');
POST値を受け取って、update_option()する。
入力された値を検証すると、以下。
$fruits = $_POST['fruits']; if ( isset( $fruits ) && in_array( $fruits, array('apple', 'banana', 'orange' ) ) ) { update_option('fruits', $fruits); }
とします。セレクトの場合は想定されているものが決まっているので、それ以外の可能性を全て排除しています。
wp_nonce_field()とcheck_admin_referer()
POSTの値が、本当にこの画面から送られてきているかを、WordPressに確認してもらうために、wp_nonce_field()
とcheck_admin_referer()
を使います。
wp_nonce_field()
の方を、formの中に書きます。
すると送信した時に、POSTに、_wp_http_referer
と_wpnonce
が自動的に含まれます。
一方のcheck_admin_referer()
は、update_optionなどその値をどこかに保存したり出力する、リスクが発生する処理の直前に設置します。
今回の例だと、下記のようになります。
<?php $fruits = $_POST['fruits']; if ( isset( $fruits ) && in_array( $fruits, array('apple', 'banana', 'orange' ) ) ) { check_admin_referer('example'); // ←ココと、 update_option('fruits', $fruits); } ?></p> <form action="" method="post"> <table> <tr valign="top"> <th scope="row"><label for="xxx">果物</label></th> <td> <select name="fruits" id="fruits"> <?php $select_options = array( array('value' => 'apple', 'text'=>'apple'), array('value' => 'banana', 'text'=>'banana'), array('value' => 'orange', 'text'=>'orange') ); foreach ($select_options as $select_option) : ?></p> <option value="<?php echo esc_attr($select_option['value']); ?>" <?php if(get_option('fruits') == $select_option['value']){ echo ' selected="selected"' } ?>><?php echo esc_attr($select_option['text']); ?></option> <p> <?php endforeach; ?> </select> </td> </tr> </table> <p><?php wp_nonce_field('example'); // ココ。 ?> </p> <p class="submit"><input type="submit" name="Submit" class="button-primary" value="変更を保存" /></p> <form>
出力するときの注意
コデックスのデータ検証を参考にする。
文字列を出力する
$text = get_option('the_key'); $safe_text = esc_html($text); echo $safe_text;
Encodes < > & ” ‘ (less than, greater than, ampersand, double quote, single quote). Will never double encode entities.
Always use when escaping user-input, in forms especially.
esc_htmlとesc_attrについて。
http://twitter.com/#!/lilyfanjp/status/125871165376954368書きかけ。。。ここに出力時の注意を足していく。
コメント
コメント一覧 (3件)
[…] また、5行目のesc_html()と10行目のwp_nonce_field()はセキュリティ対策用の関数になります。esc_html()はタグを無害化してくれる関数ですので、出力を行う際には必ず、使うようにしましょう。wp_nonce_field()については@shinichiNさんの安全なプラグイン用管理画面メモという記事で詳しく説明されています。 […]
[…] また、5行目のesc_html()と10行目のwp_nonce_field()はセキュリティ対策用の関数になります。esc_html()はタグを無害化してくれる関数ですので、出力を行う際には必ず、使うようにしましょう。wp_nonce_field()については@shinichiNさんの安全なプラグイン用管理画面メモという記事で詳しく説明されています。 […]
[…] また、値の検証など、管理画面を作る際のお作法的なことは、「安全なプラグイン用管理画面メモ」に書かれています。 […]