2013-10-18 6 views
6

登録フォームにnameフィールドが含まれているフィールドがある場合は、データベースにuser_name varchar(20)という名前で格納されます。最初に実行するのはどちらですか?サニタイズまたは検証

<?php 
if(emptiy($_pos['name']) || strlen($_post['name'])>20) 
//send an not valid input error 
else{ 
$name=htmlspcialchars($_post['name']); 
//check for sql injection; 
//insert name into database;} 
?> 

ユーザーが<i> some one </i>のような名前を挿入した場合、文字列の長さは非常に他の部分がperformeれ、名前がなる17です:それは私が次のコードでは、このフィールドの延期を検証する場合、私は、ユーザー入力 を検証すべきであることは明らかです&lt;i&gt some one &lt;/i&gt;の長さは28で、db.inに挿入している間にエラーが発生します。ユーザーに入力が間違っているとエラーが送信されると、混乱します。私は何をすべきか?最善のアプローチは何ですか?

+5

データを保存する前にエンコードする必要はありません。 mysqli_real_escape_stringなどの適切なエスケープを使用してそのままの状態で保存し、出力する前にエンコードします。これは、HTMLやJSONなどで出力する場合、別のエンコーディングが必要なためです。 –

+3

SQLインジェクションを止める最善の方法は、データベースにデータを挿入するためにmysqliまたはPDOプリペアドステートメントを使用することです。@ [Niet the Dark Absol](http://stackoverflow.com/users/507674/niet-the-dark-absol)is is mysqli_real_escape_string()関数は推奨されていません。 – nurakantech

+0

私は 'mysqli_real escape_string()'のような関数を使用することはありません。pdoを使うとより安全です。 – naazanin

答えて

6

一般的に、最初は「あなたの保護のために、そしてそれらのもの」を浄化しなければなりません。これには、無効な文字(文字コードの区別はもちろん)を取り除くことが含まれます。フィールドに文字とスペースのみを含める必要がある場合は、最初にないものを除外します。

これを実行すると、結果が検証されます。すでに使用されている名前(固有のフィールドの場合)は正しいサイズですか、空白ではありませんか?

あなたが与えた理由は、正確にはユーザーエクスペリエンスを最大限にするためです。あなたがそれを避けることができれば、ユーザーを混乱させないでください。これはダムコピー&貼り付けの動作から保護するのに役立ちますが、 "Ke $ h @"として記録された名前を使用したい場合は、 "Keh"に変更してもOKであることがあります。

第2に、バグを防ぐことでもあります。

特殊文字を許可しないユーザー名を作成するとどうなりますか?私が "Brian"と入力して、あなたのシステムがそれを既に使用中の名前として拒否した場合、私は "Brian $"を提出しますか?最初にそれを検証し、それが使用されていない場合、特殊文字を取り除き、 "Brian"を残します。うーん、今、あなたはもう一度妥当性チェックをしなければならないか、アカウントの作成に失敗した(データベースがユニークなユーザー名を要求するように設定されている場合)か、悪化するとそれが成功しオーバーライト/破損ユーザーのユーザーアカウントに発生します。

もう1つの例は、フィールドの長さの最小値です。名前の長さが3文字以上で、文字のみを受け入れる必要があり、「いいえ」と入力すると拒否します。しかし、「no @#$%」と入力すると、それが有効であるといってもいいかもしれませんが、それを消毒してもう有効ではありません。

これを避ける簡単な方法は、そして、あなたは検証について二重に考える必要はありません。

しかし、Nietは保存前にデータをエンコードしていないのが正しいです。適切なときにエンコードされるように出力をHTMLにセットアップする方が一般的にはるかに簡単です。プレーンテキスト(テキストボックス、JSON文字列などへの入力)が必要な場合は、デコードすることを忘れないようにしてください。ほとんどのテストケースでは、HTMLエンティティのデータは含まれないため、簡単にキャッチされないばかげたバグを簡単に導入できます。

大きな問題は、このようなバグが導入された場合、簡単には解決できないデータ破損にすぐにつながることです。例:プレーンテキストを持ち、HTMLエンティティとしてテキストフィールドに間違って出力し、フォームが返され、再エンコードされます。開かれた/再送信されるたびに再エンコードされます。ビジー状態のサイト/フォームでは、何千ものエンコードされたエントリで終わる可能性があります。何がHTMLでエンコードされるべきではないかを決定する明確な方法はありません。

注射からの保護は優れていますが、これを行うにはHTMLエンコーディングは設計されておらず(信頼してはいけません)、

+0

OK、あなたは玄関ブライアン$、最初のsanitezeと結果がブライアンであると仮定し、それを検証し、それがユニークであることを確かめて、あなたが登録して、ブライアンと再びフォームの私はshoulは入力を消毒するログイン?もしあなたがBrianにこんにちはを入れなければならないなら、ブライアンに入ったので混乱してしまうでしょう。$ – naazanin

+1

あなたはあなたが入力を消毒しなければならないことをユーザーに知らせなければなりません - このような状況では、ユーザーが無効であると入力すると、ユーザーにエラーが表示されます。 –

+0

@naazanin私はgdsceiに同意しますが、一般的に私はクライアント側フォーム検証の前にそのような細かい点を保存します。サーバー側で2つのモデルのいずれかを選択する可能性が高い無効な出力についてユーザーに促すことについて、より穏やかです:1)動作させ、ユーザーが気にする必要がない場合にユーザーを煩わさない知っている、または2)無効な入力を拒否し、ユーザーに何をすべきかを把握させる。これはユースケースによって異なりますが、私はグローバルな提案はできません。あなたのアプリがより国際化されるほど、潜在的に有効な文字を禁じる必要があります。 – BrianHall

2

いいえ、最初に検証する必要があります。サニタイズは、最後のステップであるデータ記憶レベルを処理するために実行されます。ビジネスルールが検証段階に合格していない場合は、データストレージレベルに近づくことはできません。数字が必要な場合に文字列を入力するとエラーになり、フォームに返信します。 SQLをプリペアドステートメントで使用し、実際には入力を破損する場合は、必要に応じてストライプスラッシュを除いてサニタイズ(5.4では不要)する必要はありません。

関連する問題