サンプル・プログラムの実行例
サンプル・プログラム
getValidNumber.php | サンプル・プログラム本体。 |
pahooInputData.php | データ入力に関わる関数群。 使い方は「数値入力とバリデーション」「文字入力とバリデーション」などを参照。include_path が通ったディレクトリに配置すること。 |
解説:入力要件など
定数 | 内 容 |
---|---|
CLASS_INT | 整数か小数か |
NUM_MIN | 最大値 |
NUM_MAX | 最小値 |
解説:数値バリデーション
241: /**
242: * 数値バリデーションを行う.
243: * 数値が整数か小数かを指定し,最小値と最大値を指定する.
244: * @参考URL https://www.pahoo.org/e-soul/webtech/phpsec/phpsec-09-01.shtm
245: * @param mixed $num バリデーションしたい数値
246: * @param string $errmsg エラーメッセージを格納する
247: * @param bool $int TRUE:整数/FALSE:小数(省略時:TRUE)
248: * @param mixed $min 最小値(省略時=-999999)
249: * @param mixed $max 最大値(省略時=+999999)
250: * @return bool TRUE:成功/FALSE:失敗
251: */
252: function validNumber($num, &$errmsg, $int=TRUE, $min=-999999, $max=+999999) {
253: //整数のパターン:PHP7.4未満に合わせた
254: static $pat_int = array(
255: '/^[\+\-]?[1-9][0-9]*$/',
256: '/^[\+\-]?0$/',
257: '/^[\+\-]?0[xX].[0-9a-fA-F]+$/',
258: '/^[\+\-]?0[oO].[0-7]+$/',
259: '/^[\+\-]?0[bB].[01]+$/'
260: );
261: //小数のパターン:PHP7.4未満に合わせた
262: static $pat_float = array(
263: '/^[\+\-]?[0-9]*[\.][0-9]+$/',
264: '/^[\+\-]?[0-9]+[eE][\+\-]?[0-9]+$/',
265: '/^[\+\-]?[0-9]*[\.][0-9]+[eE][\+\-]?[0-9]+$/'
266: );
267: $res = TRUE;
268: $errsg = '';
269:
270: //引数チェック
271: if ($min > $max) {
272: $errmsg = "最小長({$min})が最大長({$max})より大きい";
273: $res = FALSE;
274:
275: //数値バリデーション
276: } else {
277: //値の存否
278: if ($num == '' || $num == NULL) {
279: $errmsg = '数値がありません';
280: $res = FALSE;
281: //整数かどうか
282: } else if ($int) {
283: $res = FALSE;
284: foreach ($pat_int as $pat) {
285: if (preg_match($pat, $num) > 0) {
286: $res = TRUE;
287: break;
288: }
289: }
290: if (! $res) {
291: $errmsg = '整数ではありません';
292: }
293: //小数かどうか
294: } else if (!$int) {
295: $res = FALSE;
296: foreach ($pat_int as $pat) {
297: if (preg_match($pat, $num) > 0) {
298: $res = TRUE;
299: break;
300: }
301: }
302: foreach ($pat_float as $pat) {
303: if (preg_match($pat, $num) > 0) {
304: $res = TRUE;
305: break;
306: }
307: }
308: if (! $res) {
309: $errmsg = '小数ではありません';
310: }
311: }
312:
313: //最大・最小チェック
314: if ($res) {
315: if ($int) {
316: $num = (int)$num;
317: } else {
318: $num = (float)$num;
319: }
320: //最大値チェック
321: if ($num > $max) {
322: $errmsg = "最大値({$max})より大きい";
323: $res = FALSE;
324: //最小値チェック
325: } else if ($num < $min) {
326: $errmsg = "最小値({$min})より小さい";
327: $res = FALSE;
328: }
329: }
330: }
331: return $res;
332: }
まず、引数 $min と $max の大小関係に矛盾がないかどうかをチェックする。
次に数値バリデーションを行うが、下記の順序でバリデーションを行う。
- 値は存在するか(空文字ではないか)
- 入力要件が整数なら、整数にパターンマッチするか
- 入力要件が小数なら、小数にパターンマッチするか
- 最大値と最小値の範囲にあるか
整数のパターンマッチは正規表現で行うが、公式にあるPHPで取り扱い可能な整数表記を参考に、パターンを配列 $pat_int に用意した。
同様に、小数のパターンマッチも正規表現で行い、公式にあるPHPで取り扱い可能な小数表記を参考に、パターンを配列 $pat_float に用意した。入力要件が小数の時は、整数または小数のいずれかにマッチすれば要件を満たすことにした。
解説:バリデーション付き数値取得
334: /**
335: * HTML FORMで指定したINPUTの内容を数値として取り出す(バリデーション付き)
336: * filter_input()関数および $argv を参照する.
337: * @参考URL https://www.pahoo.org/e-soul/webtech/php01/php25-01.shtm
338: * @param string $key パラメータ名(省略不可)
339: * @param string $errmsg エラーメッセージを格納する(省略不可)
340: * @param mixed $def 初期値(省略時:空文字)
341: * @param bool $int TRUE:整数/FALSE:小数(省略時:TRUE)
342: * @param mixed $min 最小値(省略時=-999999)
343: * @param mixed $max 最大値(省略時=+999999)
344: * @return string 入力値
345: */
346: function getValidNumber($key, &$errmsg, $def='', $int=TRUE, $min=-999999, $max=+999999) {
347: $str = (string)getParam($key, FALSE, $def); //URLパラメータを取り出す
348: $num = trim($str); //先頭・末尾の空白文字を除く
349: $num = htmlspecialchars($num); //XSS対策
350: $res = validNumber($num, $errmsg, $int, $min, $max); //数値バリデーション
351:
352: return $str;
353: }
HTML FORMからデータを取り出すユーザー関数 getParam については、「PHPでGET/POSTでフォームから値を受け取る」を参照いただきたい。
次に、取り出したデータの先頭、末尾の空白文字を組み込み関数 trim によって取り除く。
さらに、組み込み関数 htmlspecialchars を使って特殊文字をエスケープしておく。これは後述するクロスサイトスクリプティング(XSS)対策のためである。
最後に、ユーザー関数 validNumber を使ってバリデーションを行う。
バリデーションの成否にかかわらず、入力データは、先頭・末尾の空白を取り除き、特殊文字をエスケープした状態で、戻り値とする。バリデーションで問題が発生した場合は $errmsg にエラーメッセージが入る仕組みである。
解説:メインプログラム
194: // メイン・プログラム ======================================================
195: //パラメータ
196: $errmsg = '';
197: $num = getValidNumber('num', $errmsg, '', CLASS_INT, NUM_MIN, NUM_MAX);
198:
199: //リセット
200: if (isButton('reset')) {
201: $num = '';
202: }
203:
204: //表示HTML作成
205: $HtmlBody = makeCommonBody($num, $errmsg);
206:
207: //表示
208: echo $HtmlHeader;
209: echo $HtmlBody;
210: echo $HtmlFooter;
ユーザー関数 getValidNumber を使って、バリデーション付きで数値取り出しを行い、それを画面に表示する。
クロスサイトスクリプティング(XSS)
まず第一に、入力文字列の中にHTMLタグやJavaScriptが含まれていると、プログラマは意図していないにもかかわらず、そのまま実行されてしまう。
より危険なのが、入力文字列にスクリプトやCGIが書かれている場合である。プログラムの書き方によっては、そのまま実行されてしまうことがある。下手をすると、パスワードが漏れたり、データベースの内容が改竄されてしまうことがある。
こうした攻撃をクロスサイトスクリプティング(XSS)と呼んでいる。
処理系が扱える数値の最小値/最大値
定数 | 内 容 | 備 考 |
---|---|---|
PHP_INT_MIN | 整数型の最小値 | |
PHP_INT_MAX | 整数型の最大値 | |
PHP_FLOAT_MIN | 浮動小数点型の最小値 | PHP 7.2.0 以降で利用可能 |
PHP_FLOAT_MAX | 浮動小数点型の最大値 | PHP 7.2.0 以降で利用可能 |
バリデーションとベリフィケーション
バリデーション(validation)とは、プロセスの妥当性を確認する作業である。*は、ここで用いた意味。
- 書式の設定や文字の入力場所、保存されたデータの形式などが要求通りになっているかを確認する。(*)
- 各開発工程の成果物が、当初の要求事項を満たしているかどうかを確認する。
- それが有効であるか、価値があるかどうかを検証する。
- 事件の立証や結果を法に則り認める。
ベリフィケーション(verification)とは、成果物が要求仕様通りに仕上がっているかを確認する作業である。
- 異なるプロセスを経て出力されたデータが合致するかどうかを判定する。
- 各々の開発工程の成果物が完成品として要求事項を満たしているかどうかを確認する。
- 客観的証拠を提示することによって、規定の要求事項が満たされていることを確認する。
参考サイト
- PHPでGET/POSTでフォームから値を受け取る:ぱふぅ家のホームページ
- 文字入力とバリデーション:ぱふぅ家のホームページ
入力要件を満たしていなかったり、プログラムが想定していないデータかどうかをチェックすることを、ここではバリデーション(validation)と呼ぶことにする。
今回は、入力データが数値(整数および小数)である場合、PHPで入力バリデーションを行うプログラムを作ってみることにする。
(2022年6月27日)FastCGIで正常動作しない不具合を修正
(2022年5月18日)大幅改訂,pahooInputData.php分離,PHP8対応