formhashformhash<?php
$discuzUrl = 'https://www.example.com/'; // 論壇首頁 (必須 HTTPS)
$loginUrl = $discuzUrl . 'member.php?mod=logging&action=login&loginsubmit=yes&infloat=yes&lssubmit=yes&inajax=1';
$postUrl = $discuzUrl . 'forum.php?mod=post&action=newthread&fid=2&extra=page%3D1'; // fid=版塊 ID
$cookieFile = sys_get_temp_dir() . '/dz_cookie_' . uniqid() . '.txt';
// --- 步驟 1: 取得登入 formhash ---
$ch = curl_init($loginUrl);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_COOKIEJAR => $cookieFile,
CURLOPT_SSL_VERIFYPEER => true,
CURLOPT_USERAGENT => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
]);
$html = curl_exec($ch);
curl_close($ch);
if (preg_match('/name="formhash" value="([^"]+)"/', $html, $m)) {
$loginFormhash = $m[1];
} else {
die('無法取得登入 formhash');
}
// --- 步驟 2: 提交登入 ---
$postFields = [
'formhash' => $loginFormhash,
'referer' => $discuzUrl,
'loginfield' => 'username',
'username' => 'your_username',
'password' => 'your_password',
'questionid' => 0, // 安全提問 ID (0=無)
'answer' => '', // 安全提問答案
'seccodeverify' => '', // 驗證碼 (若開啟需額外識別)
'loginsubmit' => 'true',
];
$ch = curl_init($loginUrl);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => http_build_query($postFields),
CURLOPT_COOKIEJAR => $cookieFile,
CURLOPT_COOKIEFILE => $cookieFile,
CURLOPT_REFERER => $loginUrl,
CURLOPT_SSL_VERIFYPEER => true,
CURLOPT_USERAGENT => 'Mozilla/5.0...',
]);
$html = curl_exec($ch);
curl_close($ch);
// 簡易判斷登入成功
if (strpos($html, 'succeed') === false && strpos($html, '歡迎您歸來') === false) {
die('登入失敗: ' . strip_tags($html));
}
echo "登入成功\n";
// --- 步驟 3: 取得發帖 formhash ---
$ch = curl_init($postUrl);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_COOKIEFILE => $cookieFile,
CURLOPT_SSL_VERIFYPEER => true,
CURLOPT_USERAGENT => 'Mozilla/5.0...',
]);
$html = curl_exec($ch);
curl_close($ch);
// 發帖頁 formhash 通常在
if (preg_match('/name="formhash" id="formhash" value="([^"]+)"/', $html, $m)) {
$postFormhash = $m[1];
} else {
die('無法取得發帖 formhash');
}
// --- 步驟 4: 提交發帖 ---
$postData = [
'formhash' => $postFormhash,
'subject' => '測試標題 ' . date('H:i:s'),
'message' => '這是 cURL 自動發帖測試內容。',
'topicsubmit' => 'yes',
'tags' => '測試,自動化,PHP',
'typeid' => 0, // 分類 ID (可選)
'save' => '', // 草稿箱
];
$ch = curl_init($postUrl);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => http_build_query($postData),
CURLOPT_COOKIEFILE => $cookieFile,
CURLOPT_REFERER => $postUrl, // 關鍵:防跨站提交檢查
CURLOPT_SSL_VERIFYPEER => true,
CURLOPT_USERAGENT => 'Mozilla/5.0...',
]);
$html = curl_exec($ch);
curl_close($ch);
if (strpos($html, 'succeed') !== false || strpos($html, '發帖成功') !== false) {
echo "發帖成功!\n";
} else {
echo "發帖失敗: " . strip_tags($html) . "\n";
}
// --- 步驟 5: 清理 ---
@unlink($cookieFile);
| 環節 | 關鍵點 |
|---|---|
| formhash | Discuz 防 CSRF 核心,每個表單唯一,必須動態抓取,不可硬編碼 |
| Cookie 管理 | 使用 CURLOPT_COOKIEJAR (寫入) + CURLOPT_COOKIEFILE (讀取) 維持會話 |
| Referer | 發帖時必須設定 CURLOPT_REFERER 為發帖頁 URL,否則被判定「來路不正確」 |
| User-Agent | 模擬真實瀏覽器,避免被防火牆攔截 |
| HTTPS | 現代論壇強制 HTTPS,需 CURLOPT_SSL_VERIFYPEER => true (生產環境) |
| 驗證碼 | 若開啟驗證碼,需整合 OCR 或第三方打碼平台 (超出本文範圍) |
| 安全提問 | 若帳號設有安全提問,需在登入表單帶入 questionid 和 answer |
curl_cloudflare 或使用 Selenium/Playwright 真實瀏覽器自動化。http_build_query 自動處理 URL 編碼。⚠️ 僅供授權測試、自有站點維護、學習研究使用。 未經許可自動化操作他人網站可能違反《計算機信息網絡國際聯網安全保護管理辦法》、網站服務條款,甚至構成非法侵入計算機信息系統罪。請遵守 robots.txt、API 協議、爬蟲禮儀,控制請求頻率,不濫用資源。