よっつめ

POSTで受け取った文字列をチェックするユーティリティ

『安全なWebアプリケーションの作り方 第2版』p.115 にあるサンプルファイルを少し変えてみた。
このサンプルスクリプトは、クエリー文字列(Shift_JIS)を受け取り、表示するものである。

これを配列にも対応できるようにした。
その際、array_map関数を使いたかったので、カリー化する都合上、クラスでの運用に変えた。

class PostCheck

/**
 * パラメータを取得し、文字エンコーディングチェックと変換
 * 入力値検証までおこなうクラス
 * もし、Shift_JISならば、UTF-8に変換する
 * コンストラクタ
 *   @param:
 *     $pattern -- 入力値検証用正規表現文字列
 *     $error -- 不正な場合のエラーメッセージ
 * メソッド    
 *   getParam
 *     @param:
 *       $key -- POSTパラメータ(文字列)
 *     @return:
 *       $val -- string
 *   getParamArray
 *     @param:
 *       $keyArray -- POSTパラメータ(文字列の配列)
 *     @return:
 *       array(string)
 */
class PostCheck {
  private $pattern;
  private $error;

  public function __construct( $pattern, $error ) {
    $this->pattern = $pattern;
    $this->error = $error;
  }

  public function getParam( $key ) {
    $val = filter_input( INPUT_POST, $key );
    return $this->valCheck( $val );
  }

  public function getParamArray( $keyArray ) {
    $valArray = filter_input( INPUT_POST, $keyArray, FILTER_DEFAULT,
                              FILTER_REQUIRE_ARRAY );
    return array_map( $this->valCheck, $valArray );
  }

  private function valCheck( $val ) {
    // 文字エンコーディングのチェック
    if (! mb_check_encoding( $val, 'UTF-8' )) {
      // Shift_JISならば、UTF-8に変換する
      if (mb_check_encoding( $val, 'Shift_JIS' )) {
        // 文字エンコーディングの変換 (Shift_JIS -> UTF-8)
        $val = mb_convert_encoding( $val, 'UTF-8', 'Shift_JIS' );
      }
      else {
        die( '文字エンコーディングが不正です' );
      }
    }

    // パターンによって検証
    if (preg_match( $this->pattern, $val ) !== 1) {
      die( $this->error );
    }
    return $val;
  }
}

このクラスを使うサンプル

<?php
function e( $str ) {
  return htmlspecialchars( $str, ENT_QUOTES, 'utf-8' );
}

// subject
$pattern = '/\A[[:^cntrl:]]{1,20}\z/u';
$error = '20文字以内で入力してください。改行などは使えません。';

$postCheck = new PostCheck( $pattern, $error );
$subject = $postCheck->getParam( 'subject' );
echo e($subject), "<br>\n";

// comment
$pattern = '/\A.{1,200}\z/u';
$error = '200文字以内で入力してください。';

$postCheck = new PostCheck( $pattern, $error );
$comment = $postCheck->getParam( 'comment' );
echo e($comment), "<br>\n";

// hobby
$pattern = '/\A[a-zA-Z]{1,10}\z/u';
$error = '10文字以内の英字ではありません。';

$postCheck = new PostCheck( $pattern, $error );
$arrayHobby = $postCheck->getParamArray( 'hobby' );

var_dump($arrayHobby);

$hobby = implode(",", $arrayHobby);
echo e($hobby), "<br>\n";

安全なWebアプリケーションの作り方 第2版

徳丸 浩・著
SBクリエイティブ
2018年7月19日 第2版第2刷

参考リンク

自己流のSQLインジェクション対策は危険