yano3nora
7/2/2017 - 1:04 PM

[php: filter_var/filter_input] #php #security

[php: filter_var/filter_input] Validate inputs, Email, URL ... etc by PHP. #php #security

filter_input

filter_input() - php.net
filter_input_array() - php.net
filter_input_array / filter_var_array の挙動がマニュアルの表記と違う件

スーパーグローバル $_GET, $_POST, $_SERVER, $_COOKIE などは直接触らず filter_input() を通して isset() とか型のバリデート書かなくて済むようにしたらいいよ。いっぺんに取りたいときは filter_input_array() がいいみたい。但し、これらはクセがあって結構使いづらい。


filter_var

filter_var() - php.net
filter_var_array() - php.net
フィルタの型 - php.net

PHPで整数値を検査するときどうするか。is_int() は「データ型が何か」を見るものなので、フォーム入力(GET,POST)で渡された「文字列型」を整数値かどうか判別するのには適さない。詳しくは 参考リンクを参照

そこで便利なのが filter_var() 関数。第一引数に検査する値、引数に「フィルタの挙動を決めるフラグ定数」を渡してあげる。フィルターの種類は「メールアドレス」「真偽値」「IP アドレスや MAC アドレスかどうか」「URL かどうか」など、割と豊富。

function hoge($s) {
  var_dump($s);
  var_dump(filter_var($s, FILTER_VALIDATE_INT));
  echo "\n";
}

/**
hoge(''); // false
hoge('0');
hoge('1');
hoge(1.1); // false
hoge('1.1'); // false
hoge(-10);
hoge('-10');
hoge('1e2'); // false
hoge('1.1e2'); // false
hoge('0xfa20'); // false
hoge('0b0011'); // false
hoge('0777'); // false
**/

メールアドレスのバリデーション

2019 年現在、マルチバイトメールアドレスへの各メールサービスの対応 ( Gmail など ) も始まっており ドメインの存在確認を除けば /[^\s]@[^\s]/ で表現できるくらい緩く 記号なんかも " で囲えば大体何でもイケちゃう。しかし、HTML5 の <input type="email"> などはラテン文字しか許容しなかったり、既存の様々な WEB サービスがそれぞれ独自のバリデーションを実装している関係でなんともややこしい。

PHPで各種バリデーション - qiita.com

上記で紹介されている通り PHP 7.1.0 より filter_var が UTF-8 文字列を含むバリデーションに対応しているので、これを利用するのが無難が感じがする。

function is_valid_email($email, $check_dns = false)
{
    switch (true) {
        case false === filter_var($email, FILTER_VALIDATE_EMAIL, FILTER_FLAG_EMAIL_UNICODE):
        case !preg_match('/@([^@\[]++)\z/', $email, $m):
            return false;
        // DNS チェックはドメイン部が Punycode 記法にエンコードされている必要あり
        case !$check_dns:
        case checkdnsrr($m[1], 'MX'):
        case checkdnsrr($m[1], 'A'):
        case checkdnsrr($m[1], 'AAAA'):
            return true;
        default:
            return false;
    }
}