Benutzer aus htacces Datei löschen
MaximilianK
- php
0 Multi0 Felix Riesterer0 MaximilianK0 fastix®0 MaximilianK1 dedlfix0 MaximilianK
Hallo liebe SELFHTML User,
ich sitze schon seit einiger Zeit an einem eigentlich garnicht so schwierigen Code zum Anlegen und Löschen von Usern in htaccess per PHP Oberfläche.
Die Oberfläche sieht so aus:
Der Admin soll einen Benutzernamen eingeben können (vorhandene Nutzer werden ja oben angezeigt - wenn auch noch nicht so schön) und PHP soll dann die htpasswd Datei mit file () in ein Array laden, dieses nach dem zu löschenden Namen durchsuchen und diesen mit dem ":" und Passwort löschen.
Bisher habe ich das so lösen wollen:
<?php
$Benutzername =$_POST ["Benutzerloeschen"]; //Name aus der Maske
// Liest htpasswd Datei in ein Array - liegt oberhalb des Document Root
$htpasswd_a = file ('../../../htaccess/user/.htpasswd');
//prüft, ob Benutzername in Datei
if ( false !== ($index=array_search($Benutzername,$htpasswd_a)))
{
unset ($htpasswd_a[$index]);
$fp = fopen('../../../htaccess/user/.htpasswd', 'w');
foreach($htpasswd_a as $values) fwrite($fp, $values."\n");
fclose($fp);
} else
{
echo "Benutzer nicht gefunden.";
}
?>
Ich könnte mir gut vorstellen, dass array_search () nicht ganz passt, weil er mir immer sagt "Benutzer nicht gefunden.". Ich habe mir auch schon mal mit print_r ($htpasswd_a) das Array zeigen lassen. Das Einlesen funktioniert wunderbar. Ich bekomme der Benutzernamen:Passwort<br> abgezeigt.
Würde mich über Eure Hilfe sehr freuen.
Gruß
Max
Ich könnte mir gut vorstellen, dass array_search () nicht ganz passt, weil er mir immer sagt "Benutzer nicht gefunden.".
array_search will den kompletten String haben, also username:passwort, nicht nur den Usernamen..
Ich würde in dem Fall der Arraywert am : splitten und dann nur den ersten Teil vergleichen. Am besten beim Einlesen gleich zwei Arrays anlegen, bzw. ein Array mit Usernamen als Key und Passwort als Wert.
Lieber MaximilianK,
vielleicht hilft Dir der relevante Teil in meiner Dateiverwaltung?
Liebe Grüße,
Felix Riesterer.
Vielen Dank für Eure Hilfe. Den Vorschlag von Multi und die Dateiverwaltung von Felix werde ich gleich mal ausprobieren.
Gruß
Max
Vielen Dank für Eure Hilfe. Den Vorschlag von Multi und die Dateiverwaltung von Felix werde ich gleich mal ausprobieren.
Gruß
Max
Edit: Hallo Felix, ich habe mir gerade mal deine Dateiverwaltung angesehen. Meinen Respekt, die ist ja super!
Lieber MaximilianK,
Edit: Hallo Felix, ich habe mir gerade mal deine Dateiverwaltung angesehen. Meinen Respekt, die ist ja super!
freut mich, wenn sie Dir nützt. Sie ist nicht perfekt, aber man kann sie für viele Dinge benutzen, vor allem, wenn kein FTP zur Verfügung steht (deswegen ist sie überhaupt erst entstanden).
Liebe Grüße,
Felix Riesterer.
Moin!
htpasswd-Generator - Eine Lösung für kleine Webs
MFFG (Mit freundlich- friedfertigem Grinsen)
fastix
Nochmal vielen vielen Dank für Eure Hilfe. Ich habe mir auch nochmal einen Kopf gemacht - möchte ja ordentlich PHP lernen. :-)
Es fehlt an der ein oder anderen Stelle noch ein Fehlerabfang, aber es funktioniert. Hat jemand was am Stil oder Performance auszusetzen? ;-) Bin über Kritik dankbar.
<?php
$Benutzerloeschen =$_POST ["Benutzerloeschen"]; //zu löschender Name aus der Maske
$BenutzerPasswortArray = file ("../../../htaccess/user/.htpasswd"); //laden der .htpasswd in Array
$keys = count ($BenutzerPasswortArray); //Benutzer zählen
$fp=fopen ("../../../htaccess/user/.htpasswd","w"); //öffnen der .htpasswd zum schreiben
for ($i=0; $i < $keys; $i++) //solange Zahl < Anz. Benutzer
{
$pass = substr($BenutzerPasswortArray[$i], strpos($BenutzerPasswortArray[$i],':')); //":Passwort"
$name = substr($BenutzerPasswortArray[$i],0,strpos($BenutzerPasswortArray[$i],':')); //"Benutzername"
if ($name !== $Benutzerloeschen) //Namensvergleich
{
fwrite($fp,$name.$pass); //"Benutzername:Passwort" in .htpasswd
} else
{
continue; //kein Schreiben in .htpasswd
}
}
fclose ($fp); //.htpasswd schließen
?>
Hi!
$Benutzerloeschen =$_POST ["Benutzerloeschen"]; //zu löschender Name aus der Maske
Das reine Umkopieren in eine andre Variable ist und bleibt Unfug. Zumal du die neue Variable nur ein einziges Mal verwendest kann auch das Argument der Schreibvereinfachung nicht herhalten.
$BenutzerPasswortArray = file ("../../../htaccess/user/.htpasswd"); //laden der .htpasswd in Array
$keys = count ($BenutzerPasswortArray); //Benutzer zählen$fp=fopen ("../../../htaccess/user/.htpasswd","w"); //öffnen der .htpasswd zum schreiben
An dieser Stelle hat der Request den Dateiinhalt gelöscht. Nicht weiter schlimm, er hat die Daten ja im Array. Jetzt kommt ein zweiter Request des Wegs und liest mit file() den Inhalt aus - steht nichts (mehr) drin. Der erste Request ist mittlerweile fertig und hat alles wieder brav zurückgeschrieben. Der zweite öffnet nun die Datei und verwirft den vom ersten Request geschriebenen Inhalt.
for ($i=0; $i < $keys; $i++) //solange Zahl < Anz. Benutzer
$keys ist 0, die Schleife wird nicht ausgeführt.
fclose ($fp); //.htpasswd schließen
Die leere Daten wird geschlossen. Und du fragst dich, wo deine Benutzer hin sind und warum dieser Fehler immer nur sehr spradisch auftritt und nicht wirklich nachvollziehbar ist. => Sperren von Dateien
Lo!
Danke für dein Feedback.
$BenutzerPasswortArray = file ("../../../htaccess/user/.htpasswd"); //laden der .htpasswd in Array
$keys = count ($BenutzerPasswortArray); //Benutzer zählen$fp=fopen ("../../../htaccess/user/.htpasswd","w"); //öffnen der .htpasswd zum schreiben
An dieser Stelle hat der Request den Dateiinhalt gelöscht. Nicht weiter schlimm, er hat die Daten ja im Array. Jetzt kommt ein zweiter Request des Wegs und liest mit file() den Inhalt aus - steht nichts (mehr) drin. Der erste Request ist mittlerweile fertig und hat alles wieder brav zurückgeschrieben. Der zweite öffnet nun die Datei und verwirft den vom ersten Request geschriebenen Inhalt.
for ($i=0; $i < $keys; $i++) //solange Zahl < Anz. Benutzer
Das verstehe ich jetzt nicht ganz. file () läd die .htpasswd in ein Array (löscht meines Wissens nichts - oder?) und legt für jeden "Benutzernamen:Passwort" ein neues Feld an.
Mit count gehe ich nun durch das Array und zähle die Schlüssel, um zu ermitteln wie oft ich durch die Schleife muss und Feld für Feld prüfen, ob der Feldinhalt der Eingabe entspricht.
$keys ist 0, die Schleife wird nicht ausgeführt.
Wenn ich mir $key ausgeben lasse stehen dort immer die Anzahl der vorhanden Schlüssel des $BenutzerPasswortArray drin.
fclose ($fp); //.htpasswd schließen
Die leere Daten wird geschlossen. Und du fragst dich, wo deine Benutzer hin sind und warum dieser Fehler immer nur sehr spradisch auftritt und nicht wirklich nachvollziehbar ist. => Sperren von Dateien
Hmm, meine Datei ist aber nicht leer. Sie beinhaltet nun die Benutzer (kommend aus $BenutzerPasswortArray), die ich haben möchte, also ohne den zu löschenden Benutzer aus $_POST.
Mahlzeit MaximilianK,
$fp=fopen ("../../../htaccess/user/.htpasswd","w"); //öffnen der .htpasswd zum schreiben
Das verstehe ich jetzt nicht ganz. file () läd die .htpasswd in ein Array (löscht meines Wissens nichts - oder?)
Das nicht - aber fopen('foobar', 'w') löscht (effektiv) den Inhalt der Datei. Und wenn jetzt genau kurz nach diesem Moment ein anderer Benutzer dieses Skript aufruft? Richtig: dessen "Version" versucht mittels file() den Inhalt einzulesen und findet ... genau nix.
Eine klassische Race Condition ... lies und lerne.
Mit count gehe ich nun durch das Array und zähle die Schlüssel, um zu ermitteln wie oft ich durch die Schleife muss und Feld für Feld prüfen, ob der Feldinhalt der Eingabe entspricht.
Ja, wenn *EIN* Benutzer dieses Skript *EINMAL* zur gleichen Zeit startet.
Hmm, meine Datei ist aber nicht leer. Sie beinhaltet nun die Benutzer (kommend aus $BenutzerPasswortArray), die ich haben möchte, also ohne den zu löschenden Benutzer aus $_POST.
Ja, wenn *EIN* Benutzer dieses Skript *EINMAL* zur gleichen Zeit startet.
Merke: Web-Anwendungen sind prinzipbedingt Mehrbenutzeranwendungen (außer, dieses Verhalten wird explizit verhindert) - das bedeutet, Du musst genau die Probleme, die sich bei gleichzeitigem lesenden und schreibenden Zugriff auf die gleichen Daten ergeben, behandeln.
MfG,
EKKi
Vielen Dank für deine Hilfe. Daran habe ich nicht gedacht.
Gruß
Max
Hi!
Das verstehe ich jetzt nicht ganz.
Dein Verständnis vom Ablauf ist soweit in Ordnung. Aber nur, wenn du ihn alleinstehend betrachtest. In Wirklichkeit hast du ein Mehrnutzer-System vorliegen, bei dem viele Prozesse parallel ablaufen können. Und wenn der eine Prozess gerade Daten lesen will, die ein anderer vorübergehend gelöscht hat, findet der eine nichts mehr. Deswegen musst du verhindern, dass, während der andere an den Daten arbeitet, weitere Prozesse darauf zugreifen und diese solange aussperren, bis der andere fertig ist, damit sie mit dessen Ergebnis und nicht irgendeinem Zwischenschritt weiterarbeiten.
Lo!
Ahhhhhh, *Licht aufgeh* alles klar :-)
Danke für den Link. Ich werde mich gleich daran setzen.