Beiträge von cottton

    Wenn der Codierer der Bank einen token reinprogrammiert HÄTTE, würde also Dein Link "https...deine-bank.de/geld/senden?an=cottton&wieviel=1000" auch nicht funktionieren. Richtig?

    Ja. Der csrf-token müsste ja existent sein und auf die Request passen.



    Woher erkenne ich als Anwender eigentlich, dass eine HP - Anwendung mit token abgesichert ist?

    Rechtsklick -> Element untersuchen.

    In der Form könnte es einen Token geben.

    Die können aber auch in der url stehen (macht aber kaum jemand denk ich),

    oder per Header (siehe Wiki X-XSRF-TOKEN).


    Auf den ersten Blick kann man das nicht sehen.

    Fals english ok ist:


    Sehr vereinfachtes Bsp:

    Du bist bei einer Bank "deine-bank.de" und hast Dich vor einer Minute eingeloggt.

    Ich poste hier einen Link "https...deine-bank.de/geld/senden?an=cottton&wieviel=1000"

    und Du klickst auf diesen Link.

    Dann ruft Dein Browser diese Seite auf und übermittelt die Request.


    Das geht auch via POST und still und heimlich.

    Wird im Video gut erklärt.

    Nutze $result = $sth->fetchAll()

    und dann:

    SQL
    1. SELECT* FROM 'Databasename'

    Sollte eher so aussehen

    SQL
    1. SELECT* FROM `Databasename`


    BTW: variablen gehören nicht in die Query.

    Wenn Du unbedingt den Table per var so angeben musst,

    dann bitte mit Whitelist.


    EDIT: whitelist bsp

    Passwörter werden NIEMALS in Klartext gespeichert!

    Sieh Dir das hier an: Loginpasswort richtig hashen - password_hash() & password_verify()


    Ich empfehle Die wirklich PDO statt mysqli zu nuten.

    Das ist mMn einfacher und besser documentiert.

    PDO: https://www.php.net/manual/de/book.pdo.php


    Nutze niemals Variablen in der sql-query! (egal ob mysqli oder PDO).

    Stichwort: "SQL-Injection" (google).


    Zum Ablauf: hier mal ein Rohes Bsp. mit Comments

    1st: Such mal im Netz nach "SQL-Injection". Dabei geht es um Sicherheit.

    Nutze Prepared Statements: https://www.php.net/manual/de/pdo.prepared-statements.php

    Nutze nicht ->query().


    ---

    Du hast 2 Abschnitte:

    - $s3->putObject() , was wohl ein Upload zu Amazon ist

    - INSERT INTO ..., was Dir die Infos zu dem File in Deine db schreibt


    Du kannst den Ablauf (in diesem Fall) umdrehen.

    Was mir als erstes auffällt:

    PHP
    1. for ($j=1; $j <= $anzahlzeilen; $j++) {
    2. echo "<button class='tablinks' onclick='wohnungtab(event, '$j')'>Wohnung $j</button>\n";
    3. }

    die Anführungsstriche.

    Code
    1. onclick='
    2.     wohnungtab(
    3.         event,
    4.         '$j' <-------------
    5.     )
    6. '

    ergibt

    HTML
    1. onclick='wohnungtab(event, '1')'

    sollte aber zB

    HTML
    1. onclick='wohnungtab(event, 1)'
    2. <-- oder -->
    3. onclick='wohnungtab(event, "1")'
    4. <-- oder -->
    5. onclick='wohnungtab(event, \'1\')'
    6. <-- ungetested =) -->


    Sonst kann ich auch keinen Fehler sehen.

    Stichwort: SQL-Injection


    ->query()würde ich an Deiner Stelle gleich wieder vergessen.


    Nutze prepared statements: https://www.php.net/manual/de/pdo.prepared-statements.php


    PHP
    1. $dbh = new PDO('mysql:host=localhost;dbname=test', $user, $pass);
    2. // user in users? tabelle sollte `user` heißen, und das feld `name`. Also `user`.`name`
    3. $stmt = $dbh->prepare("SELECT * FROM `users` where `user` = :uname;");
    4. $stmt->execute(['uname' => $uname]);
    5. // siehe https://www.php.net/manual/de/pdostatement.fetch.php
    6. // um rows zu ziehen (fetch)

    Eine andere Möglichkeit wird es nicht geben,

    Bestimmte Werte (wie zb die post max size usw) können nur aus der ini kommen.

    Das script läuft bereits und PHP hat schon mit den Werten "gearbeitet".


    Hier schreibt jemand per .htaccess könnte es gehen: https://stackoverflow.com/a/2773543/3411766


    Du kannst auf jeden Fall die Werte lesen.

    Lass Dir doch mal ausgeben, was die MAX-Werte sind.


    Falls Du nicht an die ini ran kommst,

    dann wäre der nächste Schritt um das Problem relativ schnell zu lösen: den Upload (die Datei) aufteilen.

    DUPLICATE - das heißt, dass ein Feld UNIQUE ist|war.


    Aber ohne genauer Fehlermeldung, kann man nur raten.

    Und ein SHOW CREATE TABLE `my_tbl_name` wäre auch nicht verkehrt.


    Ein FK kann n mal vorkommen, solange er keinen UNIQUE INDEX bekommt.

    FK "sagt nur", dass es in der Haupttabelle einen Eintrag mit der Value in der betreffenden Zeile geben muss.


    Im Bsp hat user mit id 1 drei Einträge - also 3 Adressen.

    User 2 nur eine.

    User 3 (noch) keine.


    Mit einem Foreign Key auf user_id wird es nicht möglich sein,

    in tbl user_address eine Zeile mit user_id 4 einzutragen.

    Denn es gibt keinen user mit id 5 in der Tabelle user.

    Ohne den Code, oder was er macht, angesehen zu haben


    Du nutzt eine Variable $New in der Funktion, die nicht existiert (in dieser Funktion --also in diesem Kontext).


    Der Aufruf passiert wohl hier:

    Code
    1. $New = new ClassProveContakt2();
    2. $New -> tabelle();

    Ein Fix wäre, das Object $New beim Funktionsaufruf mitzugeben:

    Ändere die Funktion - sie bekommt einen Parameter

    Code
    1. function tabelle($New) {
    2. $sb =$New->getMessages();
    3. // ...
    4. }
    5. // oder
    6. // function tabelle(ClassProveContakt2 $New) {...}
    7. // oder (falls es eine abstract class gibt)
    8. // function tabelle(AbstractClassProveContakt $New) {...}
    9. // oder (falls es ein interface gibt)
    10. // function tabelle(SoUndSoInterface $New) {...}


    Und den Aufruf:

    Code
    1. $New = new ClassProveContakt2();
    2. $New -> tabelle($New);

    Sollen User getracked werden, die registriert sind, oder alle User?

    Wenn alle, dann brauchst Du einen Browser-Fingerprint (Hab mich lange nicht mehr damit beschäftigt. Aber such mal im Netz).

    Anhand von dem Fingerprint (was ja am Ende ein Hash ist)

    kannst Du dann pro User n Einträge seines Browsers ect anlegen.


    Bsp.:

    Bei jedem Seitenaufruf prüfst Du, ob der Fingerprint in `anon_user` schon existiert - sonst anlegen.

    Bei jedem Seitenaufruf prüfst Du, ob der Browser in `browser` schon existiert - sonst anlegen.

    ---

    Jetzt könntest Du bei jedem Seitenaufruf in `anon_user_browser` eine neue Zeile einfügen.

    Dann hättest Du eine genaue Übersicht, welcher user mit welchem Browser reinkam.

    ABER das solltet Du nicht!

    Bei einem Angriff bei dem Deine Seite sehr oft aufgerufen wird, ist die Tabelle schnell voll.


    Du könntest das Ganze jetzt auf "pro Minute" oder "pro Stunde" runterdrücken.

    Aber das bedeutet (noch) mehr Aufwand.


    Wenn der Aufwand egal ist, dann:

    So, nu hättest Du also schon mal die Tabellen mit dem Browser und den Usern up-to-date.

    Geht evtl auch nocht sinnvoller.


    Du kannst ja jetzt aber nicht einfach immer wieder eine Zeile in `anon_user_browser` einfügen.

    Das erste, was mir da einfällt: Du brauchst es sicher nicht Sekundengenau.

    Also kannst Du das created_at schon mal runterdrücken auf "Jahr-Monat-Tag Stunde-Minute" (Y-m-d H:i).

    created_at könnte man dann auch umbenennen in ~"interval".


    Dazu kommt jetzt noch ein Feld `count`.

    Das Ziel:

    gibt es zu der momentanen Minute schon einen Eintrag, dann update den count +1.

    sonst insert new row mit count 1.


    Ob das Ganze jetzt Sinn macht (Aufwand<=>Nutzen), weiß ich nicht.

    Außerdem schiebst du Daten in die Datenbank, ohne diese zu escapen

    Falsche Wortwahl und|oder Du hast da evtl. auch was falsch verstanden.

    XSS passiert bei der Ausgabe (Browser).

    Hier ist aber schlimmer, dass er Userdaten direkt in eine SQL Query packt. Das schreit nach SQL-Injections.


    Daten gehören nicht escaped in die db. Aber es sollte auf keinen Fall eine Query "zusammengebastelt" werden.


    ado683 Nutze mysqli_ (oder PDO) mit Prepared Statements https://www.php.net/manual/de/…t.prepared-statements.php .

    Und htmlspecialchars() um die Daten auszugeben https://www.php.net/manual/de/function.htmlspecialchars.php .

    Keine Ausnahmen!


    Nutze === statt == .


    Was zu Hölle ist das: $_SESSION["password"] ?

    Ich hoffe, Du speicherst nicht wirklich pws in der Session. Die landen ungehasht und unverschlüsselt in Dateien auf Deinem Server (default in /tmp/).


    Auch das hier geht gar nicht: $sqlab .= " password = '" . $_POST[ "passwordUser" ] . "',";

    Passwörter gehören gehasht in die db!

    Nutze password_hash() und pasword_verify(). Siehe Loginpasswort richtig hashen - password_hash() & password_verify() .


    ---

    Um doppelte Einträge zu vermeiden, sollte (wie Du schon sagtest) ein unique index genutzt werden.

    Damit man nicht jedes mal in den SQL Fehler rennt (duplicate ...), sollte man vor dem Update ein SELECT ausführen.

    Wird zB der Name gefunden, dann existiert er offensichtlich und man kann einen Fehler ausgeben.

    Naja, Du sendest ja die Form ab, um den User zu bearbeiten -

    dann musst Du schon mitgeben, wen Du bearbeiten willst.


    $dsatz['id'] hast Du noch vom letzen Loop. Und da Du prüfst, ob es nur einen gibt, kannst Du diesen (last) User nutzen.

    Könnte man aber auch schöner aufbauen =)


    EDIT: nutze htmlspecialchars() um Ausgaben zu maskieren!

    EDIT2: Du könntest die ID auch per GET in der URL migeben. Also dann nicht mehr als POST hidden field.

    Ein Increment Script|Tool schreiben ist spannend, weil Du zB beachten musst,

    dass es gleichzeitige Zugriffe auf die Datenbank gibt.


    Mal angenommen Du hast eine normale Website mit Kunden.

    Jeder Kunde bekommt eine Kundennummer - in etwa: T-0001  (T hat hier keine Bedeutung. Soll nur zeigen, dass es einen Prefix geben können muss).


    Zwei Kd kommen gleichzeitig auf Deine Seite und registrieren sich.

    Nun musste Du sicherstellen, dass die Nummer einmalig bleibt.

    Dass machst Du als erstes hart über einen uidx (unique index) in der Datenbank.

    Es ist jetzt also schon mal nicht möglich, die gleiche Nummer "ausversehen" zu speichern.


    Wie stellst Du nun sicher, dass Du eine eeinzigartige Nummer bekommst?

    Ich gehe im Bsp nur von einer Nummer aus - ohne Prefix.

    Code
    1. // pseudocode
    2. // kunde A registriert sich:
    3. lastNumber = SELECT MAX(`number`) FROM `increment`; // die größte (zu letzt erstellte) nummber laden
    4. newNumber = lastNumber + 1; // eine neue nummer für den neuen kd
    5. // neue nummer für den kd einfügen
    6. INSERT INTO `increment` SET `number` = :new_number; // usw - zB per PHP PDO ...


    Soweit ... easy?

    Nope.

    Der gleiche Ablauf jetzt mit einem dicken fetten Haken:

    Mal angenommen Du hattest als letzte Nummer die 5 in der db,

    dann würdest Du für Kd A auf 6 hochzählen.

    Da aber - bevor Du Kd A gespeichert hast - Kd B sich auch registrieren will,

    bekommst Du für Kd B auch die 6.


    Ich hoffe, ich konnte es einigermaßen verdeutlichen.


    Was kann man da machen?

    Antwort: Die Datenbank hält die Nummer, also zählt die Datenbank die Nummer hoch. Nicht etwa das PHP Script.


    Bsp:

    Per PHP erste Query abschicken, um die Nummer zu erhöhen

    und die neue Nummer in eine Session Variable ablegen (denn UPDATE gibt uns keine Daten zurück):

    SQL
    1. UPDATE `incremnt` SET `number` = @next_session := `number` + 1;

    Jetzt eine zweite Abfrage, um die Session Variable zu lesen:

    SQL
    1. SELECT @next_session;


    Ich hab das Problem (umfangreicher natürlich) für meinen Arbeitgeber gelöst.

    Kann aber den fertigen Code nicht posten (klar).


    Aber aus der docu:


    Das war jetzt nur ein einfaches Beispiel.

    Wenn es nun aber noch mehrere Nummern (increments) geben soll - zB für user, invoice, creditmemo, ... - dann brauchst Du:

    - einen Prefix (zB O-xxx für Order, I-xxx für Invoice, ...)

    - im besten Fall eine Tabelle für alle increments

    - options wie zB Länge


    So hättest Du dann eine Tabelle für mehrere increments.

    Code
    1. beispiele:
    2. O-00054         prefix: O-    "current" or last_increment": 54    length: 7
    3. C-0421          prefix: C- "current" or last_increment": 421 length: 6
    4. K-0000004631    prefix: K- "current" or last_increment": 4631 length: 12


    Spannend =)

    ----


    Über Transactions: was @m.scatello meinte.

    Was in dem Link aber per SQL gemacht wird (START TRANSACTION, COMMIT und ROLLBACK) wird dann aber besser per PHP gesteuert.

    Siehe: https://www.php.net/manual/de/pdo.begintransaction.php

    Die Befehle wie zB "START TRANSACTION" übernimmt dann PDO für Dich.