首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

PHP $_SERVER 超全局變量深度解析:獲取域名、路徑、請求信息實戰指南

     編輯:PHP 綜合知識

前言

$_SERVER 是 PHP 最核心的超全局變量之一,包含了服務器環境、請求頭、腳本路徑等關鍵信息。本文系統梳理常用鍵值的含義、差異、安全風險與實戰用法,助你精準獲取域名、路徑、客戶端 IP 等信息。

核心鍵值對照表

鍵名含義示例值可靠性/備註
HTTP_HOST客戶端發送的 Host 頭example.com:8080可偽造,需驗證
SERVER_NAME服務器配置的主機名example.com較可靠,取決於 Apache/Nginx 配置
REQUEST_URI請求的 URI(含查詢字符串)/path/to/page?id=1&name=test不含域名,以 / 開頭
PHP_SELF當前腳本相對文檔根目錄路徑/index.php含查詢字符串時需注意 XSS
SCRIPT_FILENAME當前執行腳本的絕對路徑/var/www/html/index.php最可靠的腳本路徑
DOCUMENT_ROOTWeb 根目錄絕對路徑/var/www/htmlApache/Nginx root 指令值
REQUEST_METHODHTTP 請求方法GET/POST/PUT/DELETE標準方法
QUERY_STRING查詢字符串(不含 ?)id=1&name=test同 parse_url URL 的 query
REMOTE_ADDR客戶端 IP192.168.1.100代理下需看 X-Forwarded-For
HTTP_USER_AGENT客戶端 User-AgentMozilla/5.0...可偽造
HTTP_REFERER來源頁面 URLhttps://google.com/可為空、可偽造
HTTPS是否 HTTPS 請求on / 空Apache 模式;Nginx 需配置 fastcgi_param
SERVER_PORT服務器端口80 / 443
SERVER_PROTOCOL協議版本HTTP/1.1

實戰場景與代碼模式

1. 獲取當前完整 URL

<?php
function getCurrentUrl(): string {
    $scheme = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http';
    $host = $_SERVER['HTTP_HOST'] ?? $_SERVER['SERVER_NAME'];
    $uri = $_SERVER['REQUEST_URI'] ?? '';
    return $scheme . '://' . $host . $uri;
}
?>

2. 安全獲取客戶端真實 IP(支援代理/CDN)

<?php
function getClientIp(): string {
    $proxyHeaders = [
        'HTTP_X_FORWARDED_FOR',
        'HTTP_X_REAL_IP',
        'HTTP_CLIENT_IP',
        'HTTP_CF_CONNECTING_IP', // Cloudflare
    ];

    foreach ($proxyHeaders as $header) {
        if (!empty($_SERVER[$header])) {
            $ips = explode(',', $_SERVER[$header]);
            $ip = trim($ips[0]);
            if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {
                return $ip;
            }
        }
    }
    return $_SERVER['REMOTE_ADDR'] ?? '0.0.0.0';
}
?>

3. 判斷是否 AJAX 請求

<?php
function isAjax(): bool {
    return (isset($_SERVER['HTTP_X_REQUESTED_WITH']) 
        && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest');
}
?>

4. 獲取項目根目錄物理路徑

<?php
// 入口文件 index.php 中定義
define('ROOT_PATH', dirname($_SERVER['SCRIPT_FILENAME']));
// 或使用 __DIR__(推薦,PHP 5.3+)
define('ROOT_PATH', __DIR__);
?>

5. 構建資源絕對 URL(CDN、靜態資源)

<?php
function asset(string $path): string {
    $scheme = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http';
    $host = $_SERVER['HTTP_HOST'];
    $base = rtrim(dirname($_SERVER['SCRIPT_NAME']), '/');
    return "$scheme://$host$base/$path";
}
// 使用:asset('css/app.css') → https://example.com/project/css/app.css
?>

安全風險與防範

XSS 風險:PHP_SELF 直接輸出

<?php
// ❌ 危險:攻擊者訪問 /index.php/">
// $_SERVER['PHP_SELF'] 會包含 /">
echo '<form action="' . $_SERVER['PHP_SELF'] . '">';

// ✅ 安全:使用 htmlspecialchars 或 $_SERVER['SCRIPT_NAME']
echo '<form action="' . htmlspecialchars($_SERVER['PHP_SELF']) . '">';
// 或
echo '<form action="' . $_SERVER['SCRIPT_NAME'] . '">';
?>

Host 頭注入:HTTP_HOST 直接信任

<?php
// ❌ 危險:生成密碼重置鏈接、Canonical URL 等
$resetLink = "https://{$_SERVER['HTTP_HOST']}/reset?token=$token";

// ✅ 安全:使用配置文件定義的可信域名
$trustedHost = 'example.com'; // 從配置讀取
$resetLink = "https://$trustedHost/reset?token=$token";
?>

路徑遍歷:SCRIPT_FILENAME 拼接風險

<?php
// ❌ 危險
$file = $_SERVER['DOCUMENT_ROOT'] . $_GET['path'];

// ✅ 安全:實際路徑解析 + 白名單校驗
$requested = realpath($_SERVER['DOCUMENT_ROOT'] . '/' . $_GET['path']);
$allowed = realpath($_SERVER['DOCUMENT_ROOT'] . '/public');
if ($requested && strpos($requested, $allowed) === 0) {
    // 安全訪問
}
?>

Nginx + PHP-FPM 環境配置補充

Nginx 預設不傳遞某些變量,需在 fastcgi_params 或站點配置中顯式設置:

# nginx.conf / site.conf
fastcgi_param  SCRIPT_FILENAME    $document_root$fastcgi_script_name;
fastcgi_param  PATH_INFO          $fastcgi_path_info;
fastcgi_param  HTTPS              $https if_not_empty;
fastcgi_param  HTTP_X_FORWARDED_FOR $proxy_add_x_forwarded_for;
fastcgi_param  HTTP_X_REAL_IP     $remote_addr;

調試技巧:查看完整 $_SERVER

<?php
// 僅開發環境使用
echo '<pre>';
print_r($_SERVER);
echo '</pre>';
// 或保存到文件分析
file_put_contents('/tmp/server_dump_' . time() . '.txt', print_r($_SERVER, true));
?>

總結

$_SERVER 是通往服務器環境與請求上下文的橋樑。掌握核心鍵值語義、區分可信與不可信來源、做好輸出轉義與輸入驗證,是編寫安全、可移植 PHP 應用的基石。建議封裝為 Request 類統一訪問,集中處理代理、HTTPS、Host 等環境差異。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved