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

PHP 模擬登入實戰:Snoopy 與 cURL 兩種方案完整對比

     編輯:PHP 綜合知識

模擬登入核心流程

  1. 分析目標站點登入表單:action URL、欄位名(username/password/csrf_token)、請求方式(POST)。
  2. 發送 POST 請求攜帶帳密、CSRF Token、Cookies。
  3. 伺服器驗證成功,回應 Set-Cookie(Session ID)。
  4. 後續請求攜帶該 Cookie 存取需登入頁面。

方案一:Snoopy(輕量、類瀏覽器封裝)

注意:Snoopy 早已停止維護,PHP 7/8 相容性差,僅供舊專案參考,新專案請用 cURL 或 Guzzle。

<?php
require 'Snoopy.class.php';

$snoopy = new Snoopy();
$snoopy->agent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36';
$snoopy->referer = 'https://target.com/login';
$snoopy->cookies['PHPSESSID'] = 'known_session_if_any'; // 可預設

$loginUrl = 'https://target.com/login_check';
$postData = [
    'username' => 'your_account',
    'password' => 'your_password',
    '_token'   => 'csrf_token_from_login_page', // 需先 GET 登入頁解析
];

if ($snoopy->submit($loginUrl, $postData)) {
    // 登入成功,Cookie 已自動儲存在 $snoopy->cookies
    $snoopy->fetch('https://target.com/user/dashboard');
    echo $snoopy->results;
} else {
    echo '登入失敗: ' . $snoopy->error;
}
?>

方案二:cURL 完整實作(推薦、效能佳、功能全)

<?php
class LoginSimulator {
    private $ch;
    private $cookieFile;
    private $userAgent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0 Safari/537.36';

    public function __construct(string $cookieDir = '/tmp/cookies') {
        if (!is_dir($cookieDir)) @mkdir($cookieDir, 0755, true);
        $this->cookieFile = $cookieDir . '/cookies_' . md5($_SERVER['HTTP_HOST'] ?? 'default') . '.txt';

        $this->ch = curl_init();
        curl_setopt_array($this->ch, [
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_FOLLOWLOCATION => true,
            CURLOPT_MAXREDIRS => 5,
            CURLOPT_COOKIEJAR => $this->cookieFile,    // 儲存 Cookie
            CURLOPT_COOKIEFILE => $this->cookieFile,   // 讀取 Cookie
            CURLOPT_USERAGENT => $this->userAgent,
            CURLOPT_SSL_VERIFYPEER => false, // 僅開發測試
            CURLOPT_SSL_VERIFYHOST => false,
            CURLOPT_TIMEOUT => 30,
            CURLOPT_CONNECTTIMEOUT => 10,
        ]);
    }

    // 取得登入頁面,解析 CSRF Token
    public function getCsrfToken(string $loginPageUrl, string $tokenField = '_token'): ?string {
        curl_setopt($this->ch, CURLOPT_URL, $loginPageUrl);
        curl_setopt($this->ch, CURLOPT_POST, false);
        $html = curl_exec($this->ch);
        if ($html === false) return null;

        // 簡單正則提取 
        if (preg_match('/]+name=["\']' . preg_quote($tokenField) . '["\'][^>]+value=["\']([^"\']+)["\']/i', $html, $m)) {
            return $m[1];
        }
        // 或用 DOMDocument 更穩健
        return null;
    }

    // 執行登入
    public function login(string $loginUrl, array $credentials): bool {
        $postFields = http_build_query($credentials);
        curl_setopt($this->ch, CURLOPT_URL, $loginUrl);
        curl_setopt($this->ch, CURLOPT_POST, true);
        curl_setopt($this->ch, CURLOPT_POSTFIELDS, $postFields);
        curl_setopt($this->ch, CURLOPT_REFERER, $loginUrl);

        $response = curl_exec($this->ch);
        if ($response === false) {
            error_log('cURL error: ' . curl_error($this->ch));
            return false;
        }

        $httpCode = curl_getinfo($this->ch, CURLINFO_HTTP_CODE);
        // 判斷登入成功:302 導向、或回應包含特定文字、或 Cookie 中出現 session
        return $httpCode === 302 || stripos($response, 'logout') !== false || stripos($response, 'dashboard') !== false;
    }

    // 登入後存取受保護頁面
    public function get(string $url): ?string {
        curl_setopt($this->ch, CURLOPT_URL, $url);
        curl_setopt($this->ch, CURLOPT_POST, false);
        return curl_exec($this->ch);
    }

    public function post(string $url, array $data): ?string {
        curl_setopt($this->ch, CURLOPT_URL, $url);
        curl_setopt($this->ch, CURLOPT_POST, true);
        curl_setopt($this->ch, CURLOPT_POSTFIELDS, http_build_query($data));
        return curl_exec($this->ch);
    }

    public function __destruct() {
        curl_close($this->ch);
    }
}

// 使用範例
$sim = new LoginSimulator();
$token = $sim->getCsrfToken('https://target.com/login');
if ($token) {
    $ok = $sim->login('https://target.com/login_check', [
        'username' => 'account',
        'password' => 'pass',
        '_token' => $token,
    ]);
    if ($ok) {
        echo $sim->get('https://target.com/user/profile');
    } else {
        echo '登入失敗';
    }
} else {
    echo '無法取得 CSRF Token';
}
?>

進階:處理 JavaScript 渲染/加密登入

挑戰解決方案
密碼前端加密 (RSA/AES)逆向分析 JS 加密邏輯,用 PHP 實現同樣加密(phpseclib、openssl_encrypt)
動態 Token/簽名模擬 JS 算法生成,或用 Headless Chrome (Puppeteer/PHP-WebDriver)
驗證碼OCR 識別 (Tesseract)、打碼平台、或人工介入
雙因子認證 (2FA)TOTP 算法生成碼 (bacon/bacon-qr-code)
完整 SPA/JS 渲染改用 Puppeteer (Node) 或 PHP-WebDriver 驅動真實瀏覽器

反爬蟲繞過技巧(合法授權測試前提下)

  • 隨機化 User-Agent、Accept-Language、Referer
  • 使用住宅代理 IP 池,輪換 IP
  • 模擬真實用戶行為:隨機延遲、滑鼠軌跡、點擊路徑
  • 維持 Session 復用,避免頻繁登入
  • 處理 Set-Cookie 的 HttpOnly、Secure、SameSite 屬性

法律與道德提醒

  • 模擬登入僅限**授權測試、自有系統整合、公開資料抓取**且遵守 robots.txt 及服務條款。
  • 繞過驗證碼、破解加密、大規模暴力嘗試可能觸犯《電腦犯罪條例》等法規。
  • 建議優先尋找官方 API(OAuth、OpenID Connect),避免模擬登入脆弱性。

掌握 cURL 完整流程、Cookie 管理、CSRF 處理、錯誤重試,是 PHP 開發者進行系統整合與自動化的核心技能。

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