
Webフォームはユーザーとの重要な接点ですが、不正入力や攻撃のリスクも抱えています。特にPHPでは、適切な対策を講じないとXSSやCSRF、SQLインジェクションなどの脆弱性を招く恐れがあります。本記事では、PHPで安全にフォーム処理を行うための基本「バリデーション」「エスケープ」「CSRF対策」「SQLインジェクション対策」の実装方法を具体例付きで解説します。
目次
バリデーション:入力の正しさを確認する
バリデーションは、ユーザーからの入力が正しいかどうかを検証する処理です。不正な入力がそのまま処理されると、アプリケーションの動作に予期せぬ影響を与えることがあります。
サンプルコード:POSTデータの検証
$name = $_POST['name'] ?? '';
$email = $_POST['email'] ?? '';
$url = $_POST['url'] ?? '';
$age = $_POST['age'] ?? '';
$ip = $_POST['ip'] ?? '';
$errors = [];
if ($name === '') {
$errors[] = '名前は必須です。';
}
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$errors[] = 'メールアドレスの形式が正しくありません。';
}
if ($url && !filter_var($url, FILTER_VALIDATE_URL)) {
$errors[] = 'URLの形式が正しくありません。';
}
if ($age && !filter_var($age, FILTER_VALIDATE_INT, ["options" => ["min_range" => 1, "max_range" => 120]])) {
$errors[] = '年齢は1〜120の整数で入力してください。';
}
if ($ip && !filter_var($ip, FILTER_VALIDATE_IP)) {
$errors[] = 'IPアドレスの形式が正しくありません。';
}
主なバリデーション関数
検証内容 | 関数・手法 |
---|---|
必須入力 | empty() , isset() |
メール形式 | filter_var($email, FILTER_VALIDATE_EMAIL) |
URL形式 | filter_var($url, FILTER_VALIDATE_URL) |
整数チェック | filter_var($value, FILTER_VALIDATE_INT) |
範囲付き整数 | FILTER_VALIDATE_INT + min_range , max_range オプション |
IPアドレス | filter_var($ip, FILTER_VALIDATE_IP) |
数値かどうか | is_numeric() |
文字列の長さ制限 | strlen() |
エスケープ:表示時に無害化する
入力内容をそのままHTML出力すると、クロスサイトスクリプティング(XSS)の危険があります。PHPではhtmlspecialchars()
を使って、HTMLに変換される特殊文字を無効化できます。
サンプルコード:エスケープして表示
$name = htmlspecialchars($name, ENT_QUOTES, 'UTF-8');
$email = htmlspecialchars($email, ENT_QUOTES, 'UTF-8');
echo "<p>名前:{$name}</p>";
echo "<p>メール:{$email}</p>";
注意点
- フォームの
value
属性にもhtmlspecialchars()
を使う - DB保存時ではなく「画面に出すとき」にエスケープする
htmlspecialchars()
とfilter_var()
の違い
項目 | htmlspecialchars() | filter_var() |
目的 | HTMLのエスケープ(無害化) | 入力値の検証・正当性の確認 |
主な用途 | XSS対策(表示時) | バリデーション(受信時) |
使用タイミング | 表示直前 | 入力直後 |
例 | htmlspecialchars($str) | filter_var($email, FILTER_VALIDATE_EMAIL) |
htmlspecialchars()
は出力時の無害化を目的とし、特にHTML内で表示する際に使用します。filter_var()
は受け取ったデータが想定通りかを確認するための関数で、入力チェック(バリデーション)に使います。
この2つは補完関係にあり、filter_varで検証し、htmlspecialcharsで表示を安全にするという順序が基本です。
CSRF対策:正当なフォーム送信を保証する
CSRF(クロスサイトリクエストフォージェリ)は、ユーザーが意図しない操作を第三者に実行させる攻撃です。PHPではトークンを使った対策が一般的です。
サンプルコード:トークン生成と検証
フォーム表示時(トークン発行)
session_start();
if (empty($_SESSION['csrf_token'])) {
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
}
<form method="POST" action="form.php">
<input type="hidden" name="csrf_token" value="<?= htmlspecialchars($_SESSION['csrf_token'], ENT_QUOTES, 'UTF-8') ?>">
<!-- 他のフォーム項目 -->
<input type="submit" value="送信">
</form>
送信時の検証
session_start();
if (!isset($_POST['csrf_token']) || $_POST['csrf_token'] !== $_SESSION['csrf_token']) {
die('不正なアクセスです。');
}
SQLインジェクション対策:プリペアドステートメントの利用
SQLインジェクションとは、SQL文に悪意ある入力を混入させてデータベースを不正に操作する攻撃です。PDOやMySQLiでプリペアドステートメントを使うことで、この脅威を防ぐことができます。
サンプルコード:PDOによる安全なINSERT処理
try {
$pdo = new PDO('mysql:host=localhost;dbname=sample_db;charset=utf8', 'user', 'password');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$stmt = $pdo->prepare('INSERT INTO users (name, email) VALUES (:name, :email)');
$stmt->bindParam(':name', $name);
$stmt->bindParam(':email', $email);
$stmt->execute();
echo "登録が完了しました。";
} catch (PDOException $e) {
echo "エラー: " . $e->getMessage();
}
注意点
query()
に変数を直接渡さないprepare()
+bindParam()
/execute()
を必ず使用する- データベースのエラーメッセージは公開しない
まとめ:安全なフォーム処理でWebアプリを守る
フォームの安全性は、バリデーション・エスケープ・CSRF対策・SQLインジェクション対策の4本柱で成り立っています。以下のポイントをおさえることで、PHPフォームのセキュリティを大幅に向上させることができます。
- 入力は信用せず、厳格にバリデーション
- 画面表示には必ずエスケープ処理
- トークンを用いたCSRF対策を徹底
- DBアクセスには必ずプリペアドステートメントを使用
セキュアなフォーム実装は、ユーザー信頼の第一歩です。今回紹介したコードをベースに、実案件でも安全なフォーム処理を実現してみてください。

Contact
ウェブサイトの制作や運用に関わる
お悩みやご相談
お気軽にお問い合わせ下さい
ウェブサイトと一口に言っても、企業サイトやECサイト、ブログ、SNSなど、その“カタチ”は目的に応じてさまざまであり、構築方法や使用する技術も大きく異なります。株式会社コナックスでは、お客様のご要望やブランドの個性を丁寧に汲み取り、最適なウェブサイトの“カタチ”をご提案いたします。
デザイン、ユーザビリティ、SEO対策はもちろん、コンテンツ制作やマーケティング戦略に至るまで、あらゆるフェーズでお客様のビジネスに寄り添い、成果につながるウェブサイトづくりをサポートいたします。私たちは、ウェブサイトの公開をゴールではなくスタートと捉え、お客様のビジネスの成功に向けて共に伴走してまいります。