PHP の $_SERVER 超詳細ガイド:サーバー環境変数の実践的活用法

$_SERVER は、PHP が実行されるサーバー環境やHTTPリクエストに関する豊富なメタ情報を提供するスーパーグローバル配列です。この配列はスクリプト起動時に自動的に生成され、Webアプリケーションのルーティング、セキュリティチェック、デバッグ、URL構築などに不可欠な役割を果たします。

主な環境変数とその用途

キー名 説明 備考
SCRIPT_NAME 現在実行中のスクリプトの相対パス(例: /admin/dashboard.php 自己参照リンク作成に最適
REQUEST_URI クライアントが要求した完全なURI(クエリ文字列含む、例: /search?q=php&page=2 PHP_SELF とは異なり、改ざんリスクが低い
HTTP_HOST HTTPリクエストヘッダーの Host: 値(例: example.com:8080 ホスト名検証やマルチテナント対応で重要
REMOTE_ADDR クライアントのIPアドレス(プロキシ経由時は注意) アクセス制限・ログ記録に使用
HTTPS SSL接続時:"on"、それ以外:""(空文字) filter_var($_SERVER['HTTPS'], FILTER_VALIDATE_BOOLEAN) で安全に判定可能
SERVER_PORT サーバーが待ち受けているポート番号(例: 80, 443 URL再構築時に必須
REQUEST_TIME_FLOAT リクエスト開始時の高精度タイムスタンプ(マイクロ秒単位) PHP 5.4.0+ 導入。パフォーマンス計測に有用

実用サンプルコード

以下の関数は、信頼性の高い現在のフルURLを生成します。プロキシ環境にも対応し、HTTP/HTTPSの自動判別とポート表示を最適化します:

function buildCurrentUrl(): string
{
    $scheme = 'http';
    if (isset($_SERVER['HTTPS']) && filter_var($_SERVER['HTTPS'], FILTER_VALIDATE_BOOLEAN)) {
        $scheme = 'https';
    }
    
    $host = $_SERVER['HTTP_HOST'] ?? $_SERVER['SERVER_NAME'] ?? 'localhost';
    $port = $_SERVER['SERVER_PORT'] ?? '80';
    
    // SSLでない標準ポートは省略
    $portSuffix = ($scheme === 'https' && $port !== '443') || ($scheme === 'http' && $port !== '80')
        ? ":$port"
        : '';
    
    $uri = $_SERVER['REQUEST_URI'] ?? '/';
    
    return "$scheme://{$host}{$portSuffix}{$uri}";
}

// 使用例
echo '<p>現在のURL: ' . htmlspecialchars(buildCurrentUrl()) . '</p>';

セキュリティ上の注意点

  • HTTP_REFERER および HTTP_USER_AGENT はクライアント側で自由に偽装可能 → 決して認証・許可判断に使用しない
  • PHP_SELF をHTML出力に直接埋め込むとXSS脆弱性の原因に → 必ず htmlspecialchars() でエスケープ
  • プロキシ経由の場合、REMOTE_ADDR はプロキシのIPになるため、X-Forwarded-For ヘッダーを信頼する場合は厳密なホワイトリスト制御が必要

OS依存性への対応

WindowsとLinuxでは DOCUMENT_ROOT の末尾スラッシュ処理が異なることがあります。一貫したパス操作を行うには、次のように正規化するのが推奨されます:

function normalizeDocumentRoot(string $root): string
{
    return rtrim($root, '/\\') . '/';
}

$docRoot = normalizeDocumentRoot($_SERVER['DOCUMENT_ROOT']);
$assetPath = $docRoot . 'assets/js/main.js';

タグ: PHP web-security server-variables http-headers security-best-practices

5月25日 07:08 投稿