13

人間の名前に使用している正規表現で少し問題が発生しました。

$rexName = '/^[a-z' -]$/i';

Jürgen という名前のユーザーが登録したいとします。それともボブ?ヨーロッパではごく普通のことです。これには特別な表記法がありますか?

編集:、正規表現の作成者に対してユルゲン名を投げただけで、ü文字で単語が分割されます...

http://www.txt2re.com/index.php3?s=J%FCrgen+Blalock&submit=Show+Matches

EDIT2: そのような特定のものをチェックするのは難しいので、単に不正な文字をチェックする正規表現を使用しないのはなぜですか?

$rexSafety = "/^[^<,\"@/{}()*$%?=>:|;#]*$/i";

(ハッキングの試みで実際に使用できるのはどれですか?)

例えば。これにより、' および - 記号が許可されますが、; が必要です。SQL で動作するようにするには、それらが停止されます。SQL 攻撃の HTML インジェクションに一般的に使用される他の文字で、私が見逃しているものはありますか?

4

4 に答える 4

20

私は本当に言います:名前を検証しようとしないでください:いつの日か、あなたのコードは「間違っている」と思う名前に出会うでしょう...そして、アプリケーションが彼に「あなたの名前」を伝えたとき、どのように反応すると思いますかは有効ではありません"?

あなたが本当に達成したいことに応じて、ある種のブラックリスト/フィルターを使用して、あなたが考えた「名前ではない」を除外することを検討するかもしれません:それはおそらくいくつかの「悪い名前」を通過させますが、少なくとも、既存の名前がアプリケーションへのアクセスを妨げてはなりません。

頭に浮かぶルールの例をいくつか示します。

  • 番号なし
  • "~{()}@^$%?;:/*§£øおそらく他のいくつかのような特殊文字はありません
  • 3 つ以上のスペースはありませんか?
  • 「admin」、「support」、「moderator」、「test」、および実名を入力したくないときに人々が使用する傾向がある他のいくつかの明らかな非名前...
    • (しかし、彼らがあなたに名前を付けたくない場合でも、ランダムな文字を入力することを禁止したとしても、彼らは本名を使用することができます...それは彼らのものではありません)

はい、これは完璧ではありません。はい、一部の名前以外は通過させます...しかし、誰かに「あなたの名前が間違っている」と言うよりも、アプリケーションにとっておそらくはるかに優れています(はい、私は主張します^^)


そして、あなたが別の答えの下に残したコメントに答えるには:

SQL インジェクションと XSS 攻撃のほとんどのコマンド文字を禁止することができました。

SQL インジェクションについては、データをデータベースに送信する前にエスケープする必要があります。また、これらのデータを常にエスケープする場合 (そうするべきです!)、ユーザーが何を入力するかどうかを気にする必要はありません。エスケープされるため、常にリスクはありません。

XSS についても同様です。データを出力するときに常にデータをエスケープするため (そうするべきです!)、インジェクションのリスクはありません ;-)


編集:そのような正規表現を使用するだけでは、うまく機能しません:

次のコード:

$rexSafety = "/^[^<,\"@/{}()*$%?=>:|;#]*$/i";
if (preg_match($rexSafety, 'martin')) {
    var_dump('bad name');
} else {
    var_dump('ok');
}

少なくとも警告が表示されます:

Warning: preg_match() [function.preg-match]: Unknown modifier '{'

これらの特殊文字の少なくとも一部をエスケープする必要があります。詳細については、 PCRE パターンを掘り下げて説明します(PCRE / regex について知っておくべきことは本当にたくさんあります。すべてを説明することはできません)。

これらの文字が特定のデータ内にないことを実際に確認したい場合は、次のような結果になる可能性があります。

$rexSafety = "/[\^<,\"@\/\{\}\(\)\*\$%\?=>:\|;#]+/i";
if (preg_match($rexSafety, 'martin')) {
    var_dump('bad name');
} else {
    var_dump('ok');
}

(これは手早く汚い提案であり、洗練されなければなりません!)

これは「OK」と言っています(まあ、私は自分の名前が大丈夫であることを願っています!)
そして、次のようないくつかの特別な文字を含む同じ例:

$rexSafety = "/[\^<,\"@\/\{\}\(\)\*\$%\?=>:\|;#]+/i";
if (preg_match($rexSafety, 'ma{rtin')) {
    var_dump('bad name');
} else {
    var_dump('ok');
}

「悪い名前」と言うだろう

ただし、これを完全にテストしたわけではないことに注意してください。おそらくさらに作業が必要です。非常に慎重にテストしない限り、これをサイトで使用しないでください。


また、単一引用符は SQL インジェクションを実行しようとするときに役立つ場合があることに注意してください...しかし、おそらく一部の名前では正当な文字です...そのため、一部の文字を除外するだけでは不十分な場合があります;-)

于 2009-08-11T16:24:19.573 に答える
7

PHP の PCRE 実装は、より多くの文字セットにまたがるUnicode 文字プロパティをサポートしています。\p{L}したがって、(文字)、\p{P}(句読点)、\p{Zs}(スペース区切り文字)の組み合わせを使用できます。

/^[\p{L}\p{P}\p{Zs}]+$/

ただし、これらの文字カテゴリに含まれていない文字が含まれている場合もあれば、許可したくない文字が含まれている場合もあります。

したがって、実在の人物の名前のように値の範囲が曖昧なデータには、正規表現を使用しないことをお勧めします。


編集   質問を編集したところ、特定のコード インジェクション攻撃を防ぎたいだけであることがわかりました。潜在的な攻撃の試みとして拒否するのではなく、これらの文字を回避する必要があります。

SQL クエリ、HTML 出力、および他の言語のその他の適切な機能のために、ステートメントを使用mysql_real_escape_stringまたは準備します。htmlspecialchars

于 2009-08-11T16:17:24.593 に答える
4

これは、簡単な一般的な解決策がない問題です。問題は、名前に含まれる可能性のある文字を実際に予測できないことです。おそらく最善の解決策は、否定文字マスクを定義して、実際には名前に含めたくない特殊文字を除外することです。

以下を使用してこれを行うことができます。

$regexp = "/^[ ^ <ここに不要な文字を入れてください> ]+$/

于 2009-08-11T16:06:48.233 に答える
2

PHPで人間の名前を解析しようとしている場合は、KeithBeckmanのnameparse.phpスクリプトをお勧めします。

于 2009-11-01T02:28:56.897 に答える