本文深度解析一個功能完整的 PHP Web FTP 客戶端(ftp.php v2.2),原作者 Paul Southworth (inebria.com)。代碼實現了登錄認證、目錄瀏覽、文件上傳下載、目錄創建、權限管理等核心功能,採用模組化函數設計,配合 .htaccess 風格的單文件路由,是學習 PHP FTP 操作與 Web 應用架構的優秀教材。
switch ($function) {
case "dir": phpftp_list(...); break;
case "cd": phpftp_cd(...); break;
case "get": phpftp_get(...); break;
case "put": phpftp_put(...); break;
case "mkdir": phpftp_mkdir(...); break;
case "": phpftp_login(); break;
}
通過 $function 參數分發業務邏輯,所有操作集中在單一 ftp.php,簡化部署與權限控制。
$phpftp_host = "localhost"; // FTP 服務器
$phpftp_version = "2.2"; // 版本號
$show_version_footer = 1; // 顯示版權
$max_file_size = "1000000"; // 上傳限制 1MB
$phpftp_tmpdir = "/var/tmp/xfers"; // 臨時目錄(需 1777 權限)
$use_mime_lookup = "0"; // MIME 類型查詢擴展
function phpftp_connect($user, $pass) {
global $phpftp_host;
$ftp = ftp_connect($phpftp_host);
if ($ftp && ftp_login($ftp, $user, urldecode($pass))) {
return $ftp; // 返回流資源
}
return false;
}
關鍵點:
urldecode() 處理,支援特殊字符功能點:
ftp_chdir)與回退ftp_rawlist() 獲取原始列表drwxr-xr-x)、EPLF (匿名 FTP +r,filename)解析邏輯亮點:
$item[] = split("[ ]+", $contents[$i], 9); // 限制分割 9 段,保護文件名含空格
$item_type = substr($item[$i][0], 0, 1); // 首字符判斷類型
// d=目錄, l=鏈接, -=文件, +=EPLF格式
$tmpfile = $phpftp_tmpdir . "/" . $select_file . "." . $randval;
ftp_get($ftp, $tmpfile, $select_file, FTP_BINARY);
// MIME 類型判斷 → Header 輸出 → readfile() → unlink() 清理
設計考量:
FTP_BINARY) 保證文件完整性application/octet-stream 強制下載fread 分塊輸出move_uploaded_file($userfile, $tmpfile) // 關鍵:驗證上傳文件合法性
ftp_put($ftp, $userfile_name, $tmpfile, FTP_BINARY)
安全亮點:使用 move_uploaded_file() 防止臨時文件注入攻擊;上傳前驗證 max_file_size 隱藏欄位(雖然客戶端可繞過,需服務端 php.ini upload_max_filesize 硬限制)。
| 風險 | 影響 | 修復方案 |
|---|---|---|
| 明文傳輸密碼(HTTP + FTP) | 中間人竊取憑證 | 強制 HTTPS + FTPS (ftp_ssl_connect) / SFTP (phpseclib) |
| 會話狀態依賴 URL 參數傳遞用戶名/密碼 | 日誌洩露、瀏覽器歷史記錄、Referer 洩露 | PHP Session 存儲憑證,僅傳遞 CSRF Token |
| 無 CSRF 保護 | 偽造上傳/刪除/建目錄請求 | 所有狀態改變操作驗證 CSRF Token |
| 臨時目錄權限 1777 可能被其他用戶讀取 | 下載文件內容洩露 | 專用子目錄 + 隨機前綴 + 立即刪除 |
路徑遍歷風險($phpftp_dir 用戶可控) |
跳出 FTP 根目錄訪問敏感文件 | ftp_chdir 失敗回退、路徑正規化、chroot 限制 |
| 錯誤信息輸出 FTP 伺服器內部詳情 | 信息洩露協助攻擊 | 生產環境關閉詳細錯誤,統一友好提示 |
phpseclib/Net_SFTP 或 league/flysystem 統一 FTP/SFTP/WebDAV/S3 抽象層# 目錄權限
mkdir -p /var/tmp/xfers
chmod 1777 /var/tmp/xfers
chown www-data:www-data /var/tmp/xfers
# PHP 配置
upload_max_filesize = 100M
post_max_size = 100M
max_execution_time = 300
memory_limit = 256M
# FTP 服務器建議
# 1. 啟用 FTPS (Explicit TLS)
# 2. 限制被動模式端口範圍並防火牆放行
# 3. 啟用 chroot 限制用戶目錄
# 4. 設置磁碟配額
這個 Web FTP 客戶端雖然代碼年代久遠(2002 年),但其模組化函數設計、狀態管理、臨時文件中轉、多格式列表解析等核心模式至今仍具參考價值。理解其原理,有助於構建現代化、安全、可擴展的文件管理中台。建議在學習參考基礎上,採用成熟庫(Flysystem、phpseclib)重構生產系統,站在巨人肩膀上造輪子。