入力値の検証とは何か
入力値の検証(バリデーション)とは、プログラムが受け取った値を、使う前に決まりと照らして確かめることです。検証を飛ばすと、想定外の値が計算や保存の中へ入り、不具合や攻撃につながります。
大学の履修登録フォームを考えます。学籍番号の欄に全角の数字を打つ人も、1万字を貼りつける人も、必ずいます。
このレッスンのゴール
メモ
値を使う前に、型と長さと範囲を許可リストで確かめるコードを書ける。
今日のキーワード
| ことば | いみ | れい |
|---|---|---|
| 検証 | 値が決まりに合うかを、使う前に確かめることです。 | |
| 許可リスト | 通してよい文字や語を並べた一覧です。 | |
| 型 | 値の種類です。数、文字、真偽などがあります。 | |
| 範囲 | 値が取ってよい、最小から最大までの幅です。 | 18 から 120 |
| 正規化 | 同じ意味の値を、1つの決まった形にそろえることです。 |
学生が入力するセルは、このプレビューでは空白です。
たった1つのルール
注意
試してよいのは、自分専用のラボのコピーだけです。このラボは、わざと弱く作った店で、インターネットにはつながっていません。許可のない他人のシステムに同じことをするのは、不正アクセス禁止法に触れる犯罪です。
許可リストで確かめる
検証の基本は、通してよいものを先に決めることです。学籍番号が数字8桁なら、「数字」と「8文字」だけを通します。
「怪しい文字を探して止める」やり方は、探し忘れた文字が通ります。許可リストなら、リストにない文字は全部止まります。
数字8桁だけを通す
GOOD = "0123456789"
def is_student_no(text):
if len(text) != 8:
return False
for ch in text:
if ch not in GOOD:
return False
return True
# 文字を変えて、実行します。全角の数字は通りますか。
print(is_student_no("20250123"))
print(is_student_no("20250123"))
print(is_student_no("2025 123"))
型と長さと範囲を確かめる
値は3つの面から確かめます。型は、数か文字かなどの種類です。長さは、文字の数です。範囲は、数の最小と最大です。
3つとも守る値だけを通します。どれか1つでも外れたら、理由を短く伝えて、その値は使いません。
例: 履修登録フォームの決まり
| 欄 | 型 | 長さ・範囲 | 外れた値の例 |
|---|---|---|---|
| 名前 | 文字 | 1から20字 | 空の欄、1万字の貼りつけ |
| 年齢 | 数字だけ | 18から120 | 17、300、abc |
| 郵便番号 | 数字7桁 | ハイフンは除く | 123-45、1234567 |
| 学籍番号 | 数字だけ | ちょうど8字 | 2025 123 |
学生が入力するセルは、このプレビューでは空白です。
全角の数字は数字なのか
Python の isdigit() は、全角の「123」も数字と答えます。int() も、全角を数に直します。見た目が違っても、プログラムは数字と考えるのです。
表の文字と見た目が違うと、比べる処理や保存でずれが出ます。だから、通す文字は、"0123456789" のように自分で書いて決めます。
全角の数字を調べる
# 全角の数字は、半角と同じ文字ではありません。
print("20".isdigit())
print(int("20"))
print("20" == "20")
print("2" in "0123456789")
print("2" in "0123456789")
ラボの店に、変わった入力を送る
ラボの店に、変わった入力を3つ送りましょう。どれも見るだけです。1つ目は空の検索ことば、2つ目は60文字のことばです。
店は、どちらも断りません。3つ目はラボの店ではなく、店のコンテナに入っている Python で、全角の数字を調べます。
空の検索ことば
curl -s -G --data-urlencode "q=" http://app:8000/searchここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
60文字のことば
curl -s -o /dev/null -w "%{http_code}\n" -G --data-urlencode "q=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" http://app:8000/searchここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
全角の数字を調べる
docker exec app python -c 'print("\uff11\uff12\uff13".isdigit(), int("\uff11\uff12\uff13"))'ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
3つの答えを読む
1つ目は、公開の5つの商品を全部表示します。空の欄を、店は断らず、「何にでも合う」と読みます。2つ目は 200 を表示します。長いことばも、そのまま受け取りました。
3つ目は True 123 を表示します。全角の数字は、数字で、しかも 123 という数です。店は、この3つの面を何も確かめていません。
よくある間違い
注意
「画面の JavaScript で確かめたから、サーバーでは確かめなくてよい」と考える人がいます。それは違います。画面の確認は、利用者への親切です。攻撃する人は画面を通りません。守るのは、サーバー側の確認です。