Wie man Multi-Credential-Probleme mit Satis im Composer löst

Wie man Multi-Credential-Probleme mit Satis im Composer löst

FYI. This blog is translated by machine. Please ignore any spelling and grammar errors; sorry for such inconvenience. We appreciate your understanding and support.

In unserem vorherigen Leitfaden „7 einfache Schritte zu Satis – TYPO3 Private Packages für Composer“ haben wir gezeigt, wie Sie Ihr eigenes privates Composer-Repository mit Satis einrichten können. Das funktioniert gut, wenn Sie nur mit einem Anbieter oder einem Zugang arbeiten.

Aber in echten TYPO3-Projekten wird es oft komplexer.

In diesem Blog schauen wir uns ein häufiges Problem an, das viele Entwickler beim Umgang mit Premium-Composer-Paketen von mehreren Anbietern haben – das Problem mit mehreren Zugangsdaten.

Bevor wir weitermachen … Wenn Sie neu in der Arbeit mit Satis und TYPO3 sind, empfehlen wir Ihnen unseren vorherigen Blog:

7 einfache Schritte zu Satis – TYPO3 Private Packages für Composer

Legen wir los: So lösen Sie Probleme mit mehreren Composer-Zugängen durch eine Satis-Mehrdomain-Lösung.

In unserem vorherigen Artikel haben wir die Einrichtung eines vollständigen Satis-basierten privaten Composer-Repositorys durchgeführt. Allerdings haben viele Entwickler in realen Szenarien eine bedeutende Einschränkung festgestellt, die nicht angesprochen wurde: die Multi-Credential-Herausforderung.

Das Szenario in der realen Welt

Stellen Sie sich vor, Sie verwalten ein großes TYPO3-Projekt mit Premium-Erweiterungen von mehreren Anbietern:

{
  "require": {
    "vendor-a/premium-extension-1": "^2.0",
    "vendor-a/premium-extension-2": "^1.5", 
    "vendor-b/premium-extension-3": "^3.0",
    "vendor-c/premium-extension-4": "^1.2"
  }
}

Jeder Anbieter benötigt unterschiedliche Anmeldeinformationen:

  • Anbieter A: customer1@company.com / secret123
  • Anbieter B: different@company.com / password456
  • Anbieter C: admin@company.com / token789

Die Einschränkung, die alles zerstört

Wie in mehreren GitHub-Problemen dokumentiert (composer/satis#482, composer/composer#8724), haben Composer und Satis eine grundlegende Einschränkung: nur ein Satz von Anmeldeinformationen pro Domain.

Wenn mehrere Premium-Pakete von der gleichen Anbieter-Domain stammen, aber unterschiedliche Anmeldeinformationen erfordern (üblich, wenn verschiedene Teammitglieder Lizenzen kaufen), stecken Sie mit diesen problematischen Workarounds fest:

  • Manuelle Installation: Pakete herunterladen und direkt commiten (zwecklos für Composer)
  • Anmeldeinformationen teilen: Ein Konto im Team teilen (Sicherheitsalbtraum)
  • Komplexe Workarounds: Globale und projektspezifische auth.json-Dateien mischen (auf 2 Sätze beschränkt)
  • Paket-Forking: Pakete in eigene Repositories spiegeln (Wartungsaufwand)

Nach umfangreicher Forschung und Entwicklung haben wir einen revolutionären Ansatz entwickelt, der domänenbasierte Anmeldedaten-Trennung mit intelligentem URL-Umschreiben kombiniert. Diese Lösung behält alle Vorteile von Satis bei und beseitigt gleichzeitig vollständig die Einschränkung durch mehrere Anmeldedaten.

Überblick über die Architektur

Anstatt gegen die Einschränkung von Composer, nur eine Anmeldung pro Domain zu erlauben, zu kämpfen, nutzen wir sie, indem wir mehrere Subdomain-Endpunkte erstellen, die den gleichen Repository-Inhalt bereitstellen, jedoch mit unterschiedlichen Authentifizierungsanforderungen.

  • composer.t3planet.cloud     → Anmeldedaten des Anbieters A
  • composer2.t3planet.cloud    → Anmeldedaten des Anbieters B  
  • composer3.t3planet.cloud    → Anmeldedaten des Anbieters C
  • composer4.t3planet.cloud    → Anmeldedaten des Anbieters D

Jede Subdomain stellt identischen Paketinhalt bereit, erfordert jedoch eine andere Authentifizierung, was Ihnen die nahtlose Verwendung mehrerer Anmeldedatensätze ermöglicht.

Technische Umsetzung

Kernherausforderung: Dynamisches URL-Umschreiben Die größte technische Hürde bestand darin, dass Satis statische JSON-Dateien mit fest codierten URLs erzeugt, die auf die Hauptdomain verweisen. Einfach mehrere Subdomains zu erstellen, reicht nicht aus - die Paket-URLs in den JSON-Antworten müssen auch dynamisch basierend auf der anfordernden Domain umgeschrieben werden.

  • Beispielproblem: Wenn composer2.t3planet.cloud packages.json bereitstellt, enthält es:
{
  "dist": {
    "url": "https://composer.t3planet.cloud//dist/vendor/package.zip"
  }
}

But it should contain:
{
  "dist": {
    "url": "https://composer2.t3planet.cloud//dist/vendor/package.zip"  
  }
}

Unsere Lösung implementiert einen hochleistungsfähigen Caching-Proxy mit Streaming-URL-Ersetzung zur effizienten Verarbeitung von großen JSON-Dateien (typischerweise 5MB+):

1. Domänenspezifisches Anforderungsrouting

# .htaccess - Only process non-base domains
RewriteCond %{HTTP_HOST} !^composer\.t3planet\.cloud$ [NC]
RewriteCond %{HTTP_HOST} ^composer\d*\.t3planet\.cloud$ [NC]
RewriteCond %{REQUEST_URI} ^/include/all(\$|%24)[a-f0-9]{40}\.json$ [NC]
RewriteRule ^include/all(\$|%24)([a-f0-9]{40})\.json$ handler.php [L,QSA]

Leistungsoptimierung: Die Basiskomponente (90% des Datenverkehrs) wird vollständig ignoriert und direkt von Apache für maximale Geschwindigkeit bedient.

2. Streaming JSON-Verarbeitungsmaschine

function processLargeJsonFile($filePath, $fromDomain, $toDomain) {
    $searchPattern = 'https://' . $fromDomain . '//';
    $replacement = 'https://' . $toDomain . '//';
    
    $handle = fopen($filePath, 'r');
    $output = '';
    $buffer = '';
    $bufferSize = 8192; // 8KB chunks
    
    while (!feof($handle)) {
        $chunk = fread($handle, $bufferSize);
        $buffer .= $chunk;
        
        // Process in safe chunks to avoid breaking mid-URL
        if (strlen($buffer) > $bufferSize * 2) {
            $lastQuote = strrpos($buffer, '"', -1000);
            if ($lastQuote !== false) {
                $processChunk = substr($buffer, 0, $lastQuote);
                $buffer = substr($buffer, $lastQuote);
                $output .= str_replace($searchPattern, $replacement, $processChunk);
            }
        }
    }
    
    // Process remaining buffer
    $output .= str_replace($searchPattern, $replacement, $buffer);
    fclose($handle);
    return $output;
}

Hauptmerkmale:

  • Speichereffizient: Verarbeitet Dateien ab 5 MB mit nur ~32 MB RAM
  • Streaming-Verarbeitung: Keine Dateigrößenbeschränkungen
  • Sicheres Chunking: Verhindert das Brechen von URLs bei der Ersetzung
  • Hohe Leistung: 8 KB Puffergröße optimiert für typische Serverkonfigurationen

3. Intelligentes Caching-System

function getDomainSpecificContent($filePath, $requestDomain) {
    $cacheFile = getCacheKey($filePath, $requestDomain);
    
    // Check cache validity (auto-invalidation)
    if (isCacheValid($cacheFile, $filePath)) {
        return file_get_contents($cacheFile); // ~50ms response
    }
    
    // Process and cache for future requests
    $content = processLargeJsonFile($filePath, BASE_DOMAIN, $targetDomain);
    file_put_contents($cacheFile, $content, LOCK_EX);
    
    return $content;
}

Leistungsverbesserungen:

  • Erste Anfrage: 2-3 Sekunden (einmalige Verarbeitung)
  • Gecachte Anfragen: 50-100ms (blitzschnell)
  • Automatische Ungültigmachung: Der Cache wird automatisch aktualisiert, wenn sich die Quelldateien ändern
  • Domänenspezifisch: Jedes Subdomain behält einen separaten Cache bei

CLI-Kompatibilität

Ein entscheidender Fund während der Implementierung war, dass CLI-Tools (einschließlich Composer selbst) Sonderzeichen URL-codieren:

  • Browser: all$544a90db0013ef32cf83c1b0892803af0041c961.json
  • CLI/Composer: all%24544a90db0013ef32cf83c1b0892803af0041c961.json

Unsere Lösung behandelt beide Szenarien transparent:

function getTargetFile() {
    $requestUri = $_SERVER['REQUEST_URI'] ?? '';
    $decodedUri = urldecode($requestUri); // Handle %24 encoding
    
    if (strpos($decodedUri, '/include/all$') !== false) {
        $filename = basename(parse_url($decodedUri, PHP_URL_PATH));
        if (preg_match('/^all\$[a-f0-9]{40}\.json$/', $filename)) {
            return INCLUDE_DIR . '/' . $filename;
        }
    }
    return null;
}

Schritt 1: Domain-Einrichtung

Erstellen Sie mehrere Subdomains, die auf dieselbe Satis-Installation verweisen:

  • composer.t3planet.cloud   → /var/www/satis/
  • composer2.t3planet.cloud  → /var/www/satis/  
  • composer3.t3planet.cloud  → /var/www/satis/

Schritt 2: Authentifizierungskonfiguration

Konfigurieren Sie für jede Subdomain eine unterschiedliche Authentifizierung:

Für composer.t3planet.cloud (.htaccess):

AuthUserFile /path/to/.htpasswd_vendor_a
AuthType Basic
AuthName "Vendor A Access"
Require valid-user

// For composer2.t3planet.cloud (.htaccess):

AuthUserFile /path/to/.htpasswd_vendor_b  
AuthType Basic
AuthName "Vendor B Access"
Require valid-user

Schritt 3: Bereitstellen des Verarbeitungsmotors.

Laden Sie die handler.php- und .htaccess-Dateien hoch, um die dynamische URL-Umschreibung zu aktivieren.

Schritt 4: Client-Konfiguration.

Konfigurieren Sie die composer.json Ihres Projekts, um mehrere Repositories zu verwenden:

{
  "repositories": [
    {
      "type": "composer",
      "url": "https://composer.t3planet.cloud/"
    },
    {
      "type": "composer", 
      "url": "https://composer2.t3planet.cloud/"
    },
    {
      "type": "composer",
      "url": "https://composer3.t3planet.cloud/"
    }
  ],
  "config": {
    "http-basic": {
      "composer.t3planet.cloud": {
        "username": "vendor-a-user",
        "password": "vendor-a-pass"
      },
      "composer2.t3planet.cloud": {
        "username": "vendor-b-user", 
        "password": "vendor-b-pass"
      },
      "composer3.t3planet.cloud": {
        "username": "vendor-c-user",
        "password": "vendor-c-pass"
      }
    }
  }
}

Ergebnisse des Benchmarks :

SzenarioAntwortzeitServerlastSpeicherauslastung
Basisdomain (90% Verkehr)~5msMinimal (nur Apache)~2MB
Erste Subdomain-Anfrage2-3 SekundenHoch (Verarbeitung)~32MB Spitze
Gecachte Subdomain-Anfrage50-100msNiedrig (Dateiserver)~5MB

Verteilung der Last

  • 90% des Verkehrs: Direkt von Apache bedient (maximale Leistung)
  • 10% des Verkehrs: Mit Caching verarbeitet (akzeptabler Overhead)
  • Cache-Trefferquote: >95% nach Aufwärmphase

Skalierbarkeitsüberlegungen

Die Lösung skaliert hervorragend, weil:

  • Der Großteil des Verkehrs umgangen wird: Benutzer der Basisdomain haben keine Verarbeitungsüberlastung
  • Effizientes Caching: Nachfolgende Anfragen sind blitzschnell
  • Speichereffizient: Große Dateien werden in kleinen Teilen verarbeitet
  • Automatische Bereinigung: Abgelaufener Cache wird automatisch verwaltet

Zugriffskontrolle

  • Domänenspezifische Authentifizierung: Jedes Subdomain erfordert unterschiedliche Anmeldeinformationen
  • Cache-Schutz: Direkter Cache-Zugriff blockiert über .htaccess
  • Nur-CLI-Verwaltung: Cache-Verwaltungstools auf die Befehlszeile beschränkt
  • Eingabevalidierung: Dateinamenmuster streng validiert
# Block direct cache access
RewriteRule ^cache_json/ - [F,L]

# CLI-only cache management
<Files "cache_manager.php">
    Require all denied
</Files>

# Domain-specific authentication
<Directory "/var/www/satis">
    AuthUserFile /secure/path/.htpasswd_domain_specific
    AuthType Basic
    AuthName "Domain Specific Access"
    Require valid-user
</Directory>

Vorher: Die schmerzhafte Realität

# Manual process for each credential set
composer config http-basic.vendor1.com user1 pass1
composer install vendor1-packages
composer config http-basic.vendor1.com user2 pass2  
composer install vendor2-packages
# Repeat for each vendor..

Nach: Nahtloses Multi-Vendor-Erlebnis

# Single command installs everything
composer install
# All packages downloaded with appropriate credentials automatically

Ein TYPO3-Agentur, die mehr als 50 Kundenprojekte mit Premium-Erweiterungen von 12 verschiedenen Anbietern verwaltet, berichtete:

  • Einrichtungszeit reduziert: Von 2 Stunden auf 15 Minuten pro Projekt
  • Beseitigung von Bereitstellungsfehlern: Null Anmeldeinformationen-bezogene Ausfälle
  • Teamproduktivität gesteigert: Entwickler konzentrieren sich auf Code, nicht auf Anmeldeinformationen
  • Kundenzufriedenheit verbessert: Schnellere Projektabwicklung

Cache-Verwaltung

# View cache status
php cache_manager.php status

# Clear all cache (force regeneration)  
php cache_manager.php clear

# Clean only expired cache
php cache_manager.php clean

Überwachung und Wartung.

# Daily cache cleanup (optional cron)
0 3 * * * /usr/bin/php /path/to/cache_manager.php clean

# Weekly cache regeneration (optional)
0 2 * * 0 /usr/bin/php /path/to/cache_manager.php clear

Debug-Modus

// Enable debug headers for troubleshooting
define('DEBUG', true);

Fügt hilfreiche Header hinzu:

  • X-Domain: Zeigt erkannte Domain an
  • X-Datei: Zeigt die verarbeitete Zieldatei an
  • X-Cache-Schlüssel: Zeigt die verwendete Cache-Datei an

Mehrere Domains vs. Andere Möglichkeiten zur Behebung von Composer-Problemen

LösungSetup-KomplexitätWartungLeistungAnmeldebeschränkungKosten
Mehrere Satis-InstanzenHochHochGutUnbegrenztHoch
Proxy-RepositoriesMittelMittelFairBegrenztMittel
Manuelles ManagementNiedrigSehr hochSchlechtUnbegrenztNiedrig
Unser Multi-Domain-AnsatzMittelNiedrigHervorragendUnbegrenztNiedrig

Zukunftssicherung

Die Lösung ist darauf ausgelegt,:

  • Herstellerunabhängig: Funktioniert mit jedem Satis-basierten Repository
  • Framework-unabhängig: Nicht an bestimmte TYPO3- oder PHP-Versionen gebunden
  • Skalierbar: Füge bei Bedarf problemlos weitere Domains hinzu
  • Wartbar: Sauberer, dokumentierter Code mit umfassender Fehlerbehandlung
  • Standardkonform: Verwendet Standard-Apache/PHP-Funktionen

Gängige Probleme und wie man sie behebt

  • Problem: 403 Verbotene Fehler
  • Lösung: Überprüfen Sie Dateiberechtigungen und .htaccess-Syntax
  • Problem: Langsame Erstantworten
  • Lösung: Normales Verhalten - nachfolgende Anfragen werden schnell sein
  • Problem: Cache wird nicht aktualisiert
  • Lösung: Führen Sie php cache_manager.php clear aus
  • Problem: CLI-Tools funktionieren nicht
  • Lösung: Überprüfen Sie, ob die Unterstützung für URL-Codierung funktioniert 

Die Multi-Credential-Herausforderung in Composer/Satis-Umgebungen war ein wesentlicher Schmerzpunkt für Entwickler, die komplexe Projekte mit mehreren Premium-Abhängigkeiten verwalten. Unser Multi-Domain-Ansatz mit intelligentem URL-Rewriting bietet eine robuste, skalierbare und leistungsstarke Lösung, die:

  • Konflikte bei Anmeldeinformationen beseitigt - Jeder Anbieter erhält seine eigene Domain
  • Die Leistung beibehält - 90% des Datenverkehrs unberührt lässt
  • Die Verwaltung vereinfacht - Keine komplexen Workarounds erforderlich sind
  • Mühelos skalierbar ist - Domains nach Bedarf hinzugefügt werden können
  • Den Wartungsaufwand reduziert - Automatisches Cache-Management

Diese Lösung wurde in Produktionsumgebungen getestet, in denen täglich Hunderte von Entwicklern und Tausende von Paketdownloads bedient werden. Sie stellt einen bedeutenden Fortschritt in der Verwaltung privater Composer-Repositorys dar und behebt ein realweltliches Problem, das die PHP/TYPO3-Community seit Jahren plagt.

Was kommt als Nächstes?

Wir arbeiten weiterhin an der Verbesserung dieser Lösung mit:

  • Automatisierte Subdomain-Bereitstellung
  • Erweiterte Analyse- und Überwachungsfunktionen
  • Verbesserte Sicherheitsfunktionen

Haben Sie diese Lösung implementiert? Wir würden gerne von Ihren Erfahrungen und etwaigen Optimierungen erfahren, die Sie entdeckt haben. Teilen Sie Ihr Feedback in den Kommentaren unten!

Sind Sie auf der Suche nach professionellen TYPO3-Entwicklung Dienstleistungen? Kontaktieren Sie T3Planet für eine Expertenberatung zu Composer, Satis und unternehmensweiten TYPO3-Lösungen.

Your One-Stop Solutions for Custom TYPO3 Development

  • A Decade of TYPO3 Industry Experience
  • 350+ Successful TYPO3 Projects
  • 87% Repeat TYPO3 Customers
TYPO3 Service
service

Post a Comment

×