Webエンジニア向けプログラミング解説動画をYouTubeで配信中!
▶ チャンネル登録はこちら

【PHP8.x】FILTER_VALIDATE_URL定数の使い方

FILTER_VALIDATE_URL定数の使い方について、初心者にもわかりやすく解説します。

作成日: 更新日:

基本的な使い方

FILTER_VALIDATE_URL定数は、入力された文字列が有効なURL形式であるかを確認するためのフィルタIDを表す定数です。この定数は、PHPのfilter_var()関数やfilter_input()関数など、外部からのデータ入力を検証する際に特に有用です。例えば、ユーザーがWebフォームに入力したURLが正しい形式であるかをチェックし、不正な形式の入力を事前に防ぐ目的で利用されます。

具体的には、スキーム(http://https://など)、ホスト名、パスといったURLを構成する基本的な要素が、一般的なRFCに準拠した構文に沿っているかを検証します。IPアドレス形式のホスト名を持つURLも検証の対象となります。ただし、このフィルタは、URLが実際に存在するかどうかや、そのURLにアクセス可能であるかまでは確認しません。あくまで構文的な妥当性の判断に特化しています。より厳密な検証が必要な場合には、特定の要件を満たすオプションフラグと組み合わせて使用することで、プロトコルやパスの有無などを細かく指定することが可能です。これにより、アプリケーションのセキュリティとデータの整合性を高めるのに役立ちます。

構文(syntax)

1<?php
2$url = "http://www.example.com";
3if (filter_var($url, FILTER_VALIDATE_URL)) {
4    // URLは有効
5} else {
6    // URLは無効
7}

引数(parameters)

引数なし

引数はありません

戻り値(return)

戻り値なし

戻り値はありません

サンプルコード

PHP FILTER_VALIDATE_URLによるURL検証と注意点

1<?php
2
3/**
4 * FILTER_VALIDATE_URL定数を使用してURLの形式を検証し、
5 * その結果と潜在的なセキュリティに関する注意点を示します。
6 *
7 * この定数はfilter_var()関数とともに使用され、与えられた文字列が
8 * RFCに準拠したURL形式であるかをチェックします。しかし、形式が有効であることと、
9 * そのURLが安全であること、またはアプリケーションの意図に沿っていることは同義ではありません。
10 * 特定のURLは形式上「有効」と判断されても、セキュリティ上のリスクを持つ場合があります。
11 *
12 * @param array<string> $urls 検証するURL文字列の配列
13 */
14function validateUrlsAndHighlightSecurityRisks(array $urls): void
15{
16    echo "--- URL検証の例とセキュリティに関する注意点 ---\n\n";
17
18    foreach ($urls as $url) {
19        echo "検証中のURL: '{$url}'\n";
20        // FILTER_VALIDATE_URL定数を使ってURL形式を検証します
21        $validatedUrl = filter_var($url, FILTER_VALIDATE_URL);
22
23        if ($validatedUrl !== false) {
24            echo "  結果: 有効なURL形式です。\n";
25            // 形式上は有効ですが、セキュリティリスクやアプリケーションの意図に反する可能性があるケース
26            if (preg_match('/^ftp:\/\//i', $url)) {
27                echo "  ⚠️ 注意: FTPスキームは形式上有効ですが、アプリケーションで許可するかは別途検討が必要です。\n";
28            } elseif (preg_match('/^https?:\/\/(127\.0\.0\.1|localhost|\[::1\])/i', $url)) {
29                echo "  ⚠️ 注意: localhostや内部IPへのURLは形式上有効ですが、SSRF攻撃対策など追加の検証が必要です。\n";
30            } elseif (preg_match('/@/', $url)) {
31                echo "  ⚠️ 注意: ユーザー名とパスワードを含むURLは形式上有効ですが、認証情報をURLに含めることは推奨されません。\n";
32            }
33            // 例えば、リダイレクトURLの検証においては、外部ドメインへのリダイレクトを許容してしまう可能性があります。
34            echo "  -> フィルタリング後のURL: '{$validatedUrl}'\n";
35        } else {
36            echo "  結果: 無効なURL形式です。\n";
37        }
38        echo "\n";
39    }
40
41    echo "--- 検証完了 ---\n";
42    echo "※ FILTER_VALIDATE_URLは形式の検証のみを行います。アプリケーションの要件に応じた追加のセキュリティ検証を強く推奨します。\n";
43}
44
45// 検証するURLのリスト
46$testUrls = [
47    "http://www.example.com",                             // 標準的な有効なURL
48    "https://sub.domain.co.jp/path?query=param#fragment",   // HTTPS、パス、クエリ、フラグメントを含む有効なURL
49    "ftp://user:pass@ftp.example.com/dir/file.txt",       // FTPスキームと認証情報 (形式は有効だが、使用は非推奨)
50    "http://localhost:8080/admin",                        // localhostとポート (形式は有効だが、SSRF攻撃などに注意)
51    "http://127.0.0.1/api",                               // 内部IPアドレス (形式は有効だが、SSRF攻撃などに注意)
52    "http://[::1]/status",                                // IPv6 localhost (形式は有効だが、SSRF攻撃などに注意)
53    "http://user:password@example.com/secure",            // 認証情報を含む (形式は有効だが、非推奨)
54    "http://example.com/path/../anotherpath",             // パス正規化前のURL (形式は有効)
55    "http://example.com/?redirect=http://malicious.com",  // 形式は有効。オープンリダイレクトに注意が必要なケース
56    "not-a-valid-url",                                    // 無効な形式の例
57    "http:///invalid.com",                                // ホスト名がないため無効
58    "javascript:alert(1)",                                // URLではなくJavaScriptコードのため無効
59    "data:text/html,<script>alert(1)</script>",           // data URIスキームは通常URLとして認識されない
60];
61
62// 関数を実行し、検証結果を表示します
63validateUrlsAndHighlightSecurityRisks($testUrls);

FILTER_VALIDATE_URLはPHP 8で利用できる定数で、入力された文字列がURLとして有効な形式であるかを検証する目的で使用されます。この定数自体に引数や戻り値はありませんが、主にfilter_var()関数と組み合わせて利用されます。

サンプルコードでは、filter_var($url, FILTER_VALIDATE_URL)という形式で、URL文字列の構文がRFC(インターネット標準)に準拠しているかをチェックしています。検証の結果、形式が有効であればフィルタリングされたURL文字列が返され、無効であればfalseが返されます。これにより、URLの基本的な構造が正しいかを手軽に確認できます。

しかし、この定数による検証はあくまで「形式」のチェックにとどまります。例えば、ftp://スキームのURL、localhostや内部IPアドレスを示すURL、ユーザー名やパスワードを含むURLなどは、形式上は有効と判断されます。これらは、アプリケーションのセキュリティポリシーによっては不適切である可能性があり、SSRF(サーバーサイドリクエストフォージェリ)攻撃やオープンリダイレクト、認証情報の露出といった潜在的なセキュリティリスクにつながる場合があります。

したがって、FILTER_VALIDATE_URLはURLの基本的な形式検証には役立ちますが、アプリケーションの具体的な要件に合わせて、許可するスキームやホスト、パスなどを厳しくチェックするような、追加のセキュリティ検証を必ず実施することが強く推奨されます。

FILTER_VALIDATE_URLは、文字列が一般的なURL形式として正しいかを検証する定数です。しかし、この検証は形式が有効であることのみをチェックし、そのURLが安全であることや、アプリケーションの意図に沿っていることを保証するものではありません。例えば、形式上は有効でも、FTPスキームのURLやlocalhostへのアクセス、ユーザー名とパスワードを含むURLなどは、セキュリティ上のリスクや予期せぬ動作につながる可能性があります。SSRF攻撃やオープンリダイレクトのような脆弱性を防ぐためには、FILTER_VALIDATE_URLによる形式検証に加えて、許可するスキーム、ホスト、ポートなどを厳しく制限する独自の追加検証やサニタイズ処理が不可欠です。この定数のみに頼らず、常にアプリケーションのセキュリティ要件を考慮し、多層的な対策を講じるようにしてください。

PHPでURLを検証する

1<?php
2
3/**
4 * 指定された文字列が有効なURL形式であるかを検証し、結果を出力します。
5 *
6 * この関数は、PHPのfilter_var関数とFILTER_VALIDATE_URL定数を使用して、
7 * URLの妥当性チェックを行います。システムエンジニアを目指す初心者の方に、
8 * URL検証の基本的な方法を理解してもらうためのサンプルです。
9 *
10 * @param string $url 検証するURL文字列
11 * @return void
12 */
13function validateAndDisplayUrlStatus(string $url): void
14{
15    // filter_var関数とFILTER_VALIDATE_URL定数を使用してURLの妥当性を検証します。
16    // 有効なURLであれば、フィルタリングされた文字列(通常は元のURL)を返し、
17    // 無効なURLであれば、falseを返します。
18    if (filter_var($url, FILTER_VALIDATE_URL) !== false) {
19        echo "URL '" . $url . "' は有効です。\n";
20    } else {
21        echo "URL '" . $url . "' は無効です。\n";
22    }
23}
24
25// --- サンプルコードの実行 ---
26echo "--- URL検証の実行開始 ---\n";
27
28// 有効なURLの例
29validateAndDisplayUrlStatus("https://www.example.com");
30validateAndDisplayUrlStatus("http://localhost:8080/path?query=value#fragment");
31validateAndDisplayUrlStatus("ftp://ftp.test.org/dir/file.zip");
32
33// 無効なURLの例
34validateAndDisplayUrlStatus("example.com"); // スキーム (http://など) がないため無効
35validateAndDisplayUrlStatus("これはURLではありません");
36validateAndDisplayUrlStatus("http:// invalid-url.com"); // スペースが含まれるため無効
37validateAndDisplayUrlStatus("https://.com"); // ドメイン名が不正
38
39echo "--- URL検証の実行終了 ---\n";
40
41?>

PHP 8のこのサンプルコードは、指定された文字列が有効なURL形式であるかを検証し、その結果を表示する方法を示しています。Webアプリケーションでは、ユーザーが入力したURLの形式が正しいかを確認することが重要であり、このコードはその基本的な手法を提供します。

コードの核心は、PHPのfilter_var関数とFILTER_VALIDATE_URL定数の組み合わせです。FILTER_VALIDATE_URLは、引数を持たず、標準的なURLの構造(スキーム、ホスト名など)に沿っているかを判断するための特別な定数です。

filter_var関数は、検証したい文字列を最初の引数に、そして検証方法としてFILTER_VALIDATE_URLを二番目の引数に指定して使用します。もし入力された文字列が有効なURLであれば、filter_var関数はフィルタリングされた文字列(通常は元のURL)を返します。一方、無効なURLの場合はfalseを返します。

サンプルコードでは、validateAndDisplayUrlStatusという関数が定義されており、検証したいURL文字列を$url引数として受け取ります。この関数内でfilter_varを使ってURLの妥当性をチェックし、戻り値がfalseでないかどうかで「有効」または「無効」のメッセージを画面に出力します。validateAndDisplayUrlStatus関数の戻り値はvoidであり、値を返さずに処理を完了します。この検証方法は、不正なデータがシステムに渡されるのを防ぐ上で役立ちます。

PHPのFILTER_VALIDATE_URLは、filter_var関数と組み合わせて使用する定数で、文字列がURLの一般的な書式に沿っているかを簡単に検証できます。

注意点として、この検証はあくまで文字列の「書式」が有効であるかをチェックするものであり、そのURLが実際にインターネット上に存在するか、アクセスできるか、ネットワーク的に到達可能かまでは確認しません。例えば、「http://example.com」のような形式が正しければ有効と判断されますが、実際にそのドメインが存在しなくても有効とされます。

より厳密な検証や、実サービスでの利用を考える場合は、この書式チェックに加え、DNSルックアップによるドメインの存在確認や、実際にHTTPリクエストを送ってサーバーの応答を確認するなどの追加処理を検討する必要があります。また、ごく稀に正規のURLでも無効と判断されるケースや、その逆のケースがあることも理解しておくことが大切です。

関連コンテンツ