diff --git a/Readme.md b/Readme.md index a1fc0d5..ee8d96d 100644 --- a/Readme.md +++ b/Readme.md @@ -34,7 +34,7 @@ Ein professionelles, webbasiertes System zur Verwaltung von WLAN-Vouchers für U - JSON ### UniFi Controller -- UniFi Network Controller 6.0 oder höher +- UniFi Network Application 7.0+ mit UniFi OS (z.B. UDM, UDR, UniFi OS Server) - API-Zugriff aktiviert - Lokaler Admin-Account oder dedizierter API-User @@ -43,8 +43,8 @@ Ein professionelles, webbasiertes System zur Verwaltung von WLAN-Vouchers für U ### Schritt 1: Dateien hochladen ```bash # Repository klonen oder ZIP herunterladen -git clone https://github.com/ihr-username/unifi-voucher-system.git -cd unifi-voucher-system +git clone https://github.com/friloo/unifi-voucher-tool.git +cd unifi-voucher-tool # Dateien auf den Webserver hochladen # Stellen Sie sicher, dass der Webserver-User Schreibrechte hat @@ -131,7 +131,7 @@ rm install.php 3. Geben Sie folgende Daten ein: - **Name**: Anzeigename (z.B. "Hauptgebäude") - **Site ID**: UniFi Site ID (z.B. "default") - - **Controller URL**: URL Ihres UniFi Controllers (z.B. "https://unifi.example.com:8443") + - **Controller URL**: URL Ihres UniFi Controllers (z.B. "https://unifi.example.com:11443") - **Benutzername**: UniFi Admin-Username - **Passwort**: UniFi Admin-Passwort - **Öffentlicher Zugriff**: Aktivieren für Login-freie Nutzung @@ -291,6 +291,13 @@ RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301] - Stellen Sie sicher, dass cURL aktiviert ist - Prüfen Sie SSL-Zertifikate (CURLOPT_SSL_VERIFYPEER) +**UniFi OS: Verbindung schlägt fehl (HTTP 404 oder 401):** +- Stellen Sie sicher, dass Sie Port 11443 verwenden (nicht 8443) +- UniFi OS erfordert den Pfad `/proxy/network/api/s/{site}/...` für alle API-Aufrufe +- Der Login-Endpunkt lautet `/api/auth/login` (nicht `/api/login`) +- Ältere UniFi Network Controller ohne UniFi OS werden ab Version 2.1.0 nicht mehr unterstützt +- Bei anhaltenden 401-Fehlern: Prüfen Sie, ob der UniFi-Account lokale API-Rechte besitzt + **Voucher werden nicht erstellt:** - Überprüfen Sie die UniFi Controller Logs - Prüfen Sie API-Berechtigungen @@ -333,17 +340,26 @@ cp -r /var/www/html/voucher /backup/voucher-$(date +%Y%m%d) ## 📝 API-Dokumentation -### UniFi Controller API Endpoints +### UniFi OS API Endpoints + +> **Hinweis:** Ab Version 2.1.0 verwendet dieses Tool die UniFi OS API (Port 11443). +> Ältere Installationen mit dem klassischen UniFi Network Controller (Port 8443) müssen +> auf UniFi OS migrieren oder weiterhin Version 2.0.x verwenden. **Login:** ``` -POST /api/login +POST /api/auth/login Body: {"username": "admin", "password": "password"} +Response-Header: X-CSRF-Token: ``` +> Der `X-CSRF-Token`-Wert aus dem Login-Response-Header wird automatisch extrahiert und +> bei allen nachfolgenden POST-Anfragen als `X-CSRF-Token`-Header mitgesendet. + **Voucher erstellen:** ``` -POST /api/s/{site_id}/cmd/hotspot +POST /proxy/network/api/s/{site_id}/cmd/hotspot +Headers: X-CSRF-Token: Body: { "cmd": "create-voucher", "expire": 480, @@ -355,7 +371,14 @@ Body: { **Vouchers abrufen:** ``` -GET /api/s/{site_id}/stat/voucher +GET /proxy/network/api/s/{site_id}/stat/voucher +``` + +**Voucher löschen:** +``` +POST /proxy/network/api/s/{site_id}/cmd/hotspot +Headers: X-CSRF-Token: +Body: {"cmd": "delete-voucher", "_id": ""} ``` ## 🤝 Mitwirken @@ -402,5 +425,5 @@ Geplante Features: --- -**Version:** 2.0.0 -**Letztes Update:** Januar 2026 \ No newline at end of file +**Version:** 2.1.0 +**Letztes Update:** April 2026 \ No newline at end of file diff --git a/admin/sites.php b/admin/sites.php index 3b2e14c..e5a14f2 100644 --- a/admin/sites.php +++ b/admin/sites.php @@ -532,9 +532,9 @@ $currentUser = $auth->getCurrentUser();
+ placeholder="https://unifi.example.com:11443"> - Vollständige URL inklusive Port (meist 8443) + Vollständige URL inklusive Port (meist 11443 für UniFi OS)
diff --git a/includes/UniFiController.php b/includes/UniFiController.php index f279bb0..4ab20aa 100644 --- a/includes/UniFiController.php +++ b/includes/UniFiController.php @@ -5,7 +5,8 @@ class UniFiController { private $password; private $siteId; private $cookieFile; - + private $csrfToken = null; + public function __construct($controllerUrl, $username, $password, $siteId) { $this->controllerUrl = rtrim($controllerUrl, '/'); $this->username = $username; @@ -25,7 +26,7 @@ class UniFiController { $ch = curl_init(); curl_setopt_array($ch, [ - CURLOPT_URL => $this->controllerUrl . "/api/login", + CURLOPT_URL => $this->controllerUrl . "/api/auth/login", CURLOPT_POST => true, CURLOPT_POSTFIELDS => json_encode([ 'username' => $this->username, @@ -35,7 +36,18 @@ class UniFiController { CURLOPT_SSL_VERIFYPEER => false, CURLOPT_COOKIEJAR => $this->cookieFile, CURLOPT_COOKIEFILE => $this->cookieFile, - CURLOPT_HTTPHEADER => ['Content-Type: application/json'] + CURLOPT_HTTPHEADER => ['Content-Type: application/json'], + CURLOPT_HEADERFUNCTION => function($ch, $header) { + $parts = explode(':', $header, 2); + if (count($parts) === 2) { + $name = trim($parts[0]); + $value = trim($parts[1]); + if (strtolower($name) === 'x-csrf-token') { + $this->csrfToken = $value; + } + } + return strlen($header); + } ]); $response = curl_exec($ch); @@ -67,7 +79,12 @@ class UniFiController { CURLOPT_RETURNTRANSFER => true, CURLOPT_SSL_VERIFYPEER => false, CURLOPT_COOKIEFILE => $this->cookieFile, - CURLOPT_HTTPHEADER => ['Content-Type: application/json'] + CURLOPT_HTTPHEADER => array_filter([ + 'Content-Type: application/json', + ($method === 'POST' && $this->csrfToken !== null) + ? 'X-CSRF-Token: ' . $this->csrfToken + : null + ]) ]; if ($method === 'POST' && $data !== null) { @@ -103,8 +120,8 @@ class UniFiController { 'quota' => (int)$maxUses ]; - $response = $this->apiRequest("/api/s/{$this->siteId}/cmd/hotspot", $data); - + $response = $this->apiRequest("/proxy/network/api/s/{$this->siteId}/cmd/hotspot", $data); + if (!isset($response['data'][0]['create_time'])) { throw new Exception("Voucher konnte nicht erstellt werden"); } @@ -129,7 +146,7 @@ class UniFiController { // Alle Voucher abrufen public function getVouchers() { - $response = $this->apiRequest("/api/s/{$this->siteId}/stat/voucher"); + $response = $this->apiRequest("/proxy/network/api/s/{$this->siteId}/stat/voucher"); return $response['data'] ?? []; } @@ -196,8 +213,8 @@ class UniFiController { '_id' => $voucherId ]; - $response = $this->apiRequest("/api/s/{$this->siteId}/cmd/hotspot", $data); - + $response = $this->apiRequest("/proxy/network/api/s/{$this->siteId}/cmd/hotspot", $data); + return isset($response['meta']['rc']) && $response['meta']['rc'] === 'ok'; }