Add UniFi API diagnostic section to test.php

Shows raw login HTTP code, all response headers, X-CSRF-Token extraction
(header + cookie file fallback), login response body, cookie file contents,
and a follow-up stat/voucher GET to verify the full auth+API flow.

https://claude.ai/code/session_01UsuvFAmmeagtQa14QA4iaq
This commit is contained in:
Claude 2026-04-22 05:35:15 +00:00
parent dbce0299d6
commit e705458af3
No known key found for this signature in database

151
test.php
View file

@ -84,6 +84,157 @@ echo "<h2>7. Session</h2>";
echo "Session Status: " . session_status() . " (1=disabled, 2=active)<br>";
echo "Session ID: " . session_id() . "<br>";
// 8. UniFi API Diagnose
echo "<h2>8. UniFi API Diagnose</h2>";
try {
$db2 = Database::getInstance();
$site = $db2->fetchOne("SELECT * FROM sites WHERE is_active = 1 ORDER BY id ASC LIMIT 1");
if (!$site) {
echo "✗ Keine aktive Site in der Datenbank gefunden<br>";
} else {
echo "Site: <strong>" . htmlspecialchars($site['name']) . "</strong><br>";
echo "Controller URL: <code>" . htmlspecialchars($site['unifi_controller_url']) . "</code><br>";
echo "Site ID: <code>" . htmlspecialchars($site['site_id']) . "</code><br>";
echo "Username: <code>" . htmlspecialchars($site['unifi_username']) . "</code><br>";
echo "<br>";
// --- Raw Login Test ---
echo "<strong>Login-Test (raw cURL):</strong><br>";
$cookieFile = tempnam(sys_get_temp_dir(), 'UNIFI_TEST_');
$csrfToken = null;
$controllerUrl = rtrim($site['unifi_controller_url'], '/');
$ch = curl_init();
$responseHeaders = [];
curl_setopt_array($ch, [
CURLOPT_URL => $controllerUrl . "/api/auth/login",
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode([
'username' => $site['unifi_username'],
'password' => $site['unifi_password']
]),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_COOKIEJAR => $cookieFile,
CURLOPT_COOKIEFILE => $cookieFile,
CURLOPT_TIMEOUT => 10,
CURLOPT_CONNECTTIMEOUT => 5,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'Origin: ' . $controllerUrl,
'Referer: ' . $controllerUrl . '/login',
],
CURLOPT_HEADERFUNCTION => function($ch, $header) use (&$csrfToken, &$responseHeaders) {
$responseHeaders[] = rtrim($header);
$parts = explode(':', $header, 2);
if (count($parts) === 2 && strtolower(trim($parts[0])) === 'x-csrf-token') {
$csrfToken = trim($parts[1]);
}
return strlen($header);
}
]);
$body = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$curlErr = curl_error($ch);
$info = curl_getinfo($ch);
curl_close($ch);
if ($curlErr) {
echo "✗ cURL Fehler: " . htmlspecialchars($curlErr) . "<br>";
} else {
$icon = ($httpCode === 200) ? '✓' : '✗';
echo "$icon HTTP Code: <strong>$httpCode</strong><br>";
echo "Effective URL: <code>" . htmlspecialchars($info['url']) . "</code><br>";
}
// Response headers
echo "<br><strong>Response-Header:</strong><pre style='background:#f4f4f4;padding:8px;font-size:12px'>";
foreach ($responseHeaders as $h) {
if ($h !== '') echo htmlspecialchars($h) . "\n";
}
echo "</pre>";
// CSRF token
if ($csrfToken !== null) {
echo "✓ X-CSRF-Token aus Header: <code>" . htmlspecialchars($csrfToken) . "</code><br>";
} else {
echo "✗ Kein X-CSRF-Token im Login-Response-Header gefunden<br>";
// Check cookie file fallback
if (file_exists($cookieFile)) {
$tokenFromCookie = null;
foreach (file($cookieFile) as $line) {
$line = trim($line);
if ($line === '' || $line[0] === '#') continue;
$parts = explode("\t", $line);
if (count($parts) >= 7 && strtoupper($parts[5]) === 'TOKEN') {
$tokenFromCookie = $parts[6];
}
}
if ($tokenFromCookie) {
echo "✓ CSRF-Token aus Cookie-Datei (Fallback): <code>" . htmlspecialchars($tokenFromCookie) . "</code><br>";
$csrfToken = $tokenFromCookie;
} else {
echo "✗ Auch kein TOKEN-Cookie in der Cookie-Datei gefunden<br>";
}
}
}
// Response body
echo "<br><strong>Login Response Body:</strong><pre style='background:#f4f4f4;padding:8px;font-size:12px;max-height:200px;overflow:auto'>";
echo htmlspecialchars(substr($body, 0, 2000));
echo "</pre>";
// Cookie file contents
if (file_exists($cookieFile)) {
$cookieContents = file_get_contents($cookieFile);
echo "<strong>Cookie-Datei:</strong><pre style='background:#f4f4f4;padding:8px;font-size:12px'>";
echo htmlspecialchars($cookieContents ?: '(leer)');
echo "</pre>";
}
// --- API Test (only if login succeeded) ---
if ($httpCode === 200) {
echo "<strong>API-Test (stat/voucher GET):</strong><br>";
$apiHeaders = ['Content-Type: application/json'];
if ($csrfToken !== null) {
$apiHeaders[] = 'X-CSRF-Token: ' . $csrfToken;
}
$ch2 = curl_init();
curl_setopt_array($ch2, [
CURLOPT_URL => $controllerUrl . "/proxy/network/api/s/" . $site['site_id'] . "/stat/voucher",
CURLOPT_HTTPGET => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_COOKIEFILE => $cookieFile,
CURLOPT_TIMEOUT => 10,
CURLOPT_CONNECTTIMEOUT => 5,
CURLOPT_HTTPHEADER => $apiHeaders,
]);
$apiBody = curl_exec($ch2);
$apiCode = curl_getinfo($ch2, CURLINFO_HTTP_CODE);
$apiErr = curl_error($ch2);
curl_close($ch2);
if ($apiErr) {
echo "✗ cURL Fehler: " . htmlspecialchars($apiErr) . "<br>";
} else {
$icon2 = ($apiCode === 200) ? '✓' : '✗';
echo "$icon2 HTTP Code: <strong>$apiCode</strong><br>";
}
echo "<strong>API Response Body:</strong><pre style='background:#f4f4f4;padding:8px;font-size:12px;max-height:200px;overflow:auto'>";
echo htmlspecialchars(substr($apiBody, 0, 2000));
echo "</pre>";
}
@unlink($cookieFile);
}
} catch (Exception $e) {
echo "✗ Diagnose-Fehler: " . htmlspecialchars($e->getMessage()) . "<br>";
}
echo "<hr>";
echo "<h2>✓ Test abgeschlossen</h2>";
echo "<p><a href='login.php'>Zum Login</a> | <a href='index.php'>Zur Startseite</a></p>";