1

私は、データベース挿入前のフィルターの非常に広範なリストを実行していますが、コードがどれだけ長くて醜いかについて、かなりうんざりしています。

/*******************************************************************
* START OF sanitising input 
********************************************************************/
// main user inputs
$title  = filter_var($place_ad['title'], FILTER_SANITIZE_STRING); 
$desc   = filter_var($place_ad['desc'], FILTER_SANITIZE_SPECIAL_CHARS);
$cat_1  = filter_var($place_ad['cat_1'], FILTER_SANITIZE_NUMBER_INT);
$cat_2  = filter_var($place_ad['cat_2'], FILTER_SANITIZE_NUMBER_INT);
$cat_3  = filter_var($place_ad['cat_3'], FILTER_SANITIZE_NUMBER_INT);
$price  = filter_var($place_ad['price'], FILTER_SANITIZE_NUMBER_FLOAT,FILTER_FLAG_ALLOW_FRACTION);
$suffix = filter_var($place_ad['suffix'], FILTER_SANITIZE_STRING); 

// check input
if(empty($title) || strlen($title) < 3 || strlen($title) > 100) { $error[] = 'Title field empty, too long or too short.'; }
if(empty($desc) || strlen($desc) < 3 || strlen($place_ad['desc']) > 5000) { $error[] = 'Description field empty, too long or too short.'; } 
if(empty($cat_1) || empty($cat_2)) { $error[] = 'You did not select a category for your listing.'; }
if(empty($price) || $price < 0 || $price > 1000000) { $error[] = 'Price field empty, too low or too high.'; }


// google location stuff
$lat    = filter_var($place_ad['lat'], FILTER_SANITIZE_NUMBER_FLOAT,FILTER_FLAG_ALLOW_FRACTION);    
$lng    = filter_var($place_ad['lng'], FILTER_SANITIZE_NUMBER_FLOAT,FILTER_FLAG_ALLOW_FRACTION);
$formatted_address   = filter_var($place_ad['formatted_address'], FILTER_SANITIZE_STRING);

// check input
if(empty($lat) || empty($lng)) { $error[] = 'Location error. No co-ordinates for your location.'; }


// account type
$registered = filter_var($place_ad['registered'], FILTER_SANITIZE_NUMBER_INT);


// money making extras
$extras = filter_var($place_ad['extras'], FILTER_SANITIZE_NUMBER_INT); //url encoded string
$icons  = filter_var($place_ad['icons'], FILTER_SANITIZE_STRING); //url encoded string
$premium= filter_var($place_ad['premium'], FILTER_SANITIZE_NUMBER_INT); //numeric float;
$bump   = filter_var($place_ad['bump'], FILTER_SANITIZE_NUMBER_INT); //numeric float;


// user details field
if ($registered == '1') // Registering as new user
{

    $type   = filter_var($place_ad['n_type'], FILTER_SANITIZE_NUMBER_INT);
    $name   = filter_var($place_ad['n_name'], FILTER_SANITIZE_STRING);
    $phone  = filter_var($place_ad['n_phone'], FILTER_SANITIZE_STRING);
    $email  = filter_var($place_ad['n_email'], FILTER_SANITIZE_EMAIL);
    $pass   = filter_var($place_ad['n_password'], FILTER_UNSAFE_RAW);

    if(empty($type)) { $error[] = 'Type field error.'; }
    if(empty($name) || strlen($name) > 100) { $error[] = 'You did not enter your name or name too long.'; }
    if(empty($email) || strlen($email) < 5 || strlen($email) > 100) { $error[] = 'You did not enter a valid email.'; }
    if(!filter_var($email, FILTER_VALIDATE_EMAIL)) { $error[] = 'You did not enter a valid email.'; }
    if(empty($pass) || strlen($pass) < 6 || strlen($pass) > 100) { $error[] = 'Your password must be at least 6 characters.'; }

}
elseif ($registered =='2') // registered user
{
    $email  = filter_input($place_ad['n_email'], FILTER_SANITIZE_EMAIL);
    $pass   = filter_input($place_ad['n_password'], FILTER_UNSAFE_RAW);

    if(empty($email) || strlen($email) < 5 || strlen($email) > 100) { $error[] = 'You did not enter a valid email.'; }
    if(empty($pass) || strlen($pass) < 6 || strlen($pass) > 100) { $error[] = 'Your password must be at least 6 characters.'; }
}
elseif ($registered == '3') // dont wanna register details
{
    $name   = filter_input($place_ad['n_name'], FILTER_SANITIZE_STRING);
    $phone  = filter_input($place_ad['n_phone'], FILTER_SANITIZE_STRING);
    $email  = filter_input($place_ad['n_email'], FILTER_SANITIZE_EMAIL);

    if(empty($name) || strlen($name) > 100) { $error[] = 'You did not enter your name or name too long.'; }
    if(empty($email) || strlen($email) < 5 || strlen($email) > 100) { $error[] = 'You did not enter a valid email.'; }

}
/*******************************************************************
* END OF Sanitising input
********************************************************************/

私のコードの多くは「不要」であると考えていますが、それを削除するとしたら、コーディングの習慣が悪いのではないかと思います。

たとえばFILTER_SANITIZE_NUMBER、データベースがフィールドで正しく設定されているため、すべての * フィルターを破棄できINT/FLOATます。

また、多くの「> より大きい」チェックを捨てることもできます。それらのほとんどは、ユーザーが大量のデータを入力するのを防ぐためだけに存在するためです (ただし、これはデータベース フィールドの長さによって制限されます)。

他の誰もがこれほど醜いユーザー入力検証コードを持っていますか?

- - - - - - - - - 編集 - - - - - - - - - - -

情報をありがとうございました。私は PDO を使用しているので、もう少し圧縮しようと思うかもしれませんが、次のことを質問できますか。

  1. ラジオ ボタンや選択ボックスなどの入力フィールドで、ユーザーが入力を簡単に壊すことができない場合、PDO 定数をバインドするだけで十分だと思いますか? これらの値は、db の enum および tinyint(1) フィールドに結び付けられており、フォーム仕様の外でこれらの値を操作しても、ユーザーは何も達成できません。
  2. また、filter_var を使用して、UTF8 でエンコードされたページでの表示に適したユーザー入力を作成しています。これは実際には <> と他のいくつかの文字をエンティティにエンコードするだけだと思います。htmlentities を使用するだけでよいでしょうか?
4

2 に答える 2

2

IMO、扱いにくそうに見えますが、ユーザーに通知し、入力されたデータを修正してもらいたい場合は、アプリ層ですべての検証の明らかな過剰が必要です。それ以外の場合は、クエリの値をバインドするときにPDO 定数を割り当てて、データ アクセス レイヤー (たとえば PDO) にデータをサニタイズさせることができます。

サニタイズ プロセスは必要に応じて複雑にすることも簡単にすることもできます。必要なのは、どの構成がニーズに最も適しているかを判断することだけです。

- - アップデート - - -

コードをそれほど圧倒しないようにするためのいくつかの提案。これは、Zend やSymfony Validator Componentなどのベンダー ライブラリをロードできないことを前提としています。

class Validator
{
    public function validateString($string, array $options)
    {
        $min = ((isset($options['min'])) && (strlen($options['min'] > 1))) ? $options['min'] : null;
        $max = ((isset($options['max'])) && (strlen($options['max'] > 1))) ? $options['max'] : null;

        $string = filter_var($string, FILTER_SANITIZE_STRING);

        if (empty($string)) {
            throw new Exception(sprintf('Empty value: %s', $string));
        }

        if ((false === is_null($min) && (strlen($string) < $min)) {
            throw new Exception(sprintf('Value too short: %s', $string));
        }

        if ((false === is_null($max) && (strlen($string) > $max)) {
            throw new Exception(sprintf('Value too long: %s', $string));
        }
    }

    return $string;
}

// Calling code

try {
    $title = Validator::validateString($place_ad['title'], array('min' => 3, 'max' => 100));
} catch (Exception $e) {
    $errors[] = 'Title field empty, too long or too short.';
    // OR
    $errors[] = $e->getMessage();
}

try {
    $title = Validator::validateString($place_ad['desc'], array('min' => 3, 'max' => 5000));
} catch (Exception $e) {
    $errors[] = 'Description field empty, too long or too short.';
    // OR
    $errors[] = $e->getMessage();
}

うまくいけば、あなたは絵を手に入れます。メソッドをデータ型に対して汎用にし、一連のオプションで柔軟にすることで、コードを再利用してフットプリントを削減しながら、達成したいデータ サニタイズ レベルを維持することができます。

于 2013-03-21T22:56:05.903 に答える
-2

情報が (HTML の一部として) Web サイトに表示されると仮定すると、次の 2 つのことを行う必要があります。

  1. データベースクエリのサニタイズ (または準備済みステートメントを使用)
  2. HTML 表示用にサニタイズします。

1 つ目は簡単です。mysqli または PDO を定期的に使用している場合は、その方法を既に知っているはずです。この件に関する質問は次のとおりです: PHP PDO 準備済みステートメント

あなたの場合、2番目はよりトリッキーです。各変数を調べて、クリーニング関数に渡す必要があります。それhtmlspecialcharsか、HTML Purifier などのより積極的な HTML フィルターです。この件に関する質問があります:文字列から特定のタグと特定の属性を削除する方法は? .

配列に値がある場合は、array_walkorarray_mapを使用して配列全体を数行でサニタイズできます。

于 2013-03-21T22:50:14.810 に答える