HTML PHP JS -> Von URL ID auslesen und Webseite entsprechend anzeigen

izoards

Bekanntes Mitglied
Hi,

Ich möchte aus der URL eine Information lesen und danach die DB Abfrage starten und die Daten entsprechend auf der Seite anzeigen.
Bin da auf folgendes Tutorial gestossen, was dieser Anforderung bereits sehr nahe kommt:
https://www.allphptricks.com/create-and-consume-simple-rest-api-in-php/

Soweit habe ich das an meine Umgebung / Anforderung angepasst und es funktioniert. Ich habe nun ein Feld / Formular, wo ich die Anfrage auslösen kann.
Gibt es eine Möglichkeit, dass ich dieser manuelle Anfrage Prozess umgehen kann? Also dass die URL eben bereits die Information beinhaltet?

Mit Punkt 3 des Tutorials, kann ich die JSON Daten anzeigen lassen, jedoch weiss ich nicht, ob ich nun dort auch direkt die Webseite einbauen kann?

Ich hoffe Ihr versteht was ich meine...
Vielen Dank bereits jetzt für die Hilfe und Inputs...
 

mihe7

Top Contributor
Jetzt muss ich erstmal mit etwas anfangen, das gar nichts mit der Sache zu tun hat:
Bin da auf folgendes Tutorial gestossen
das SQL-Injection zulässt. Man baut keine Werte, die von außen kommen, in eine SQL-Abfrage ein. Unter keinen Umständen. Niemals.

Schreib das SQL mit Platzhaltern, rufe prepare auf und binde die Platzhalter an die Werte.

Gibt es eine Möglichkeit, dass ich dieser manuelle Anfrage Prozess umgehen kann?
Wie meinst Du das? Du brauchst kein Formular, Du kannst eine Anfrage auch per JS-Code senden.

Also dass die URL eben bereits die Information beinhaltet?
Kann man machen, will man aber nicht immer, da die Anfragen z. B. in Logfiles landen. Ansonsten wird das ja schon in Schritt 3 gezeigt: hier wird ein Query-Parameter über $GET gelesen. Du kannst natürlich auch Werte aus dem Pfad (s. z. B. REQUEST_URI usw.) lesen. In dem Fall muss aber die URL umgeschrieben werden (URL-Rewrite), damit der Webserver das Dokument nicht im Dateisystem sucht. Das funktioniert oft mit einer einfachen .htaccess-Datei (Apache).

Die Zeilen
Code:
RewriteEngine On
RewriteRule rest/. api.php
würden zum Beispiel alle Anfragen, die an einen Pfad gestellt werden, der mit rest/ beginnt an das api.php-Skript umleiten. In dem Skript kann dann der Pfad ausgewertet werden, z. B. mit
PHP:
$parts = explode("/", filter_input(INPUT_SERVER, "REQUEST_URI"));

Stellt man nun eine Anfrage an http://meinserver/rest/a/b/c, dann wäre $parts ein Array
PHP:
[
  0 =>
  1 => "a",
  2 => "b",
  3 => "c"
]
 

izoards

Bekanntes Mitglied
das SQL-Injection zulässt.
Das dachte ich eben auch.
Ich dachte eben mit dieser Rest API wurde dies verhindert.
Wenn ich über diese Seite:
https://pentest-tools.com/website-vulnerability-scanning/sql-injection-scanner-online

meine url: http://meinServer.net/api.php

teste, kommt hier kein Hinweis, dass dies gefährdet wäre...!?

obwohl ich mit http://meinServer.net/api.php/72
den Eintrag der SQL Abfrage erhalte. Also wäre eine SQL injection hier schon möglich, oder?

Schreib das SQL mit Platzhaltern, rufe prepare auf und binde die Platzhalter an die Werte.
Das tönt kompliziert.... Gibts dazu irgendwo ein Beispiel?

Wie meinst Du das? Du brauchst kein Formular, Du kannst eine Anfrage auch per JS-Code senden.
Ich möchte halt über eine personalisierte URL per QR Code Scan, direkt den entsprechenden Inhalt anzeigen.
-> Das ist dann wohl nicht möglich, da ich ja für das immer eine Information über die URL mitgeben muss und diese dann in die SQL Abfrage einbauen muss.
 

izoards

Bekanntes Mitglied
Kann man machen, will man aber nicht immer, da die Anfragen z. B. in Logfiles landen.
Log Files habe ich entdeckt. Haufenweise .goutputstream-xxxx files. Die kann ich irgendwie auch gar nicht löschen... Sind das die angesprochenen Log Files?

Da muss ich wohl nochmals über die Bücher...

Ein Tutorial wie man so etwas macht, wäre sehr hilfreich 🙏
 

mihe7

Top Contributor
Ich dachte eben mit dieser Rest API wurde dies verhindert.
Nö, die "REST"-API hat ja nichts mit SQL zu tun. Du bekommst einen String von außen und wenn Du den einfach in einen SQL-String einbaust, kannst Du natürlich auch SQL einfügen. Du kannst ja mal ?q=1%20OR%201%3D1 an die URL hängen, dann wird aus dem SQL
SQL:
SELECT * FROM `transactions` WHERE order_id=1 OR 1=1
Das tönt kompliziert.... Gibts dazu irgendwo ein Beispiel?
Das ist ganz einfach:
https://www.php.net/manual/de/mysqli-stmt.bind-param.php hat gesagt.:
PHP:
$stmt = $mysqli->prepare("INSERT INTO CountryLanguage VALUES (?, ?, ?, ?)");
$stmt->bind_param('sssd', $code, $language, $official, $percent);
Hier siehst Du die Platzhalter ? im Statement und darunter werden diese an die Werte gebunden. Der erste Parameter gibt die Typen an, hier also drei Strings (s) und ein Fließkommawert (d). Die restlichen Parameter sind eben die Werte.

Wenn Du Dich fragst, was hier der Unterschied ist: hier hast Du ein prepared Statement, d. h. beim prepare wird die Anfrage an die DB gesendet, die die SQL-Anfrage kompiliert. Das Ergebnis ist somit eine kompilierte Anfrage, die nichts mehr mit SQL zu tun hat - daher ist auch keine SQL-Injection mehr möglich.

Ich möchte halt über eine personalisierte URL per QR Code Scan, direkt den entsprechenden Inhalt anzeigen.
OK, das ist ja kein Problem. Das ist halt dann ein einfacher GET-Request, Du kannst ja z. B. https://meinserver/meineResource?q=1234 in einen QR-Code klatschen.

Das ist dann wohl nicht möglich, da ich ja für das immer eine Information über die URL mitgeben muss und diese dann in die SQL Abfrage einbauen muss.
Wie gesagt: kein Problem, einfach die Infos per als Argument an ein prepared Statement binden.

Sind das die angesprochenen Log Files?
Nein, ich meine die Log-Files des Webservers (z. B. access log), dort findest Du eben die angefragten URLs. Es kommt halt darauf an, welche Daten man über die URL versendet. Wenn es nichts sensibles ist, ist das kein Problem. Dir muss halt klar sien, dass alles, was in einer URL auftaucht, in der Regel auch in irgendeinem Logfile landet.

Ein Tutorial wie man so etwas macht, wäre sehr hilfreich 🙏
Das Tutorial, das Du da hast, sollte doch passen. Den SQL-Teil würde ich aus genannten Gründen halt so nicht übernehmen.

Wenn es um eine einzige URL mit GET-Request geht, ist das mit PHP ja sehr einfach - und da würde ich auch nicht groß rumeiern: alles in ein Skript, fertig. Wenn Du dagegen was größeres vorhast, würde ich mir Gedanken über die Struktur machen und die Zuständigkeiten sauber trennen.

Anzumerken wäre vielleicht noch, dass das Tutorial mit "REST" streng genommen gar nichts zu tun hat. Dort wird einfach ein HTTP-Request mit einem JSON-Dokument beantwortet. REST ist als Architekturstil etwas mehr als das, bei dem es in erster Linie darum geht, Hypermedia für Zustandsübergänge der Anwendung zu verwenden (HATEOAS). Aber das nur nebenbei.
 

izoards

Bekanntes Mitglied
Du kannst ja mal ?q=1%20OR%201%3D1
Das habe ich soeben mal gemacht, id 1 hat kein Eintrag, darum habe ich es auf 72 geändert. Aber es kommt "invalid" request...
Vielleicht mache ich was falsch... Darfst sonst gerne mal selbst versuchen: http://zusellipi.ddns.net/api.php
http://zusellipi.ddns.net/apiTest.php ist dann mit "Forumular eingabe...
(Zur Info, oder_id habe auf ID geändert...) mit http://zusellipi.ddns.net/api/72 kommen die Daten....

https://www.php.net/manual/de/mysqli-stmt.bind-param.php hat gesagt.:

PHP:
$stmt = $mysqli->prepare("INSERT INTO CountryLanguage VALUES (?, ?, ?, ?)");
$stmt->bind_param('sssd', $code, $language, $official, $percent);
Vielen Dank, das probiere ich demnächst umzusetzen :)

Das ist halt dann ein einfacher GET-Request, Du kannst ja z. B. https://meinserver/meineResource?q=1234 in einen QR-Code klatschen.
Cool, das ist mein Ziel

Wenn es nichts sensibles ist, ist das kein Problem. Dir muss halt klar sien, dass alles, was in einer URL auftaucht, in der Regel auch in irgendeinem Logfile landet.
Ist zum Glück nichts sensibles.. Habe auch keine Verschlüsselung (https://....)

Wenn es um eine einzige URL mit GET-Request geht, ist das mit PHP ja sehr einfach - und da würde ich auch nicht groß rumeiern: alles in ein Skript, fertig. Wenn Du dagegen was größeres vorhast, würde ich mir Gedanken über die Struktur machen und die Zuständigkeiten sauber trennen.
Genau, ein Skript, ist nicht was grosses..
 
Zuletzt bearbeitet:

izoards

Bekanntes Mitglied
so:

PHP:
<?php
//https://www.allphptricks.com/create-and-consume-simple-rest-api-in-php/ok
header("Content-Type:application/json");
if (isset($_GET['ID']) && $_GET['ID']!="") {
    include('config.php');
    $order_id = $_GET['ID'];
    $result = mysqli_query(
    $con,
    "SELECT * FROM `CO2Data` WHERE ID=$order_id");
    if(mysqli_num_rows($result)>0){
    $row = mysqli_fetch_array($result);
    $amount = $row['Wert'];
    $latitude = $row['Latitude'];
    $longitude = $row['Longitude'];
    response($order_id, $amount, $latitude,$longitude);
    mysqli_close($con);
    //echo "<h1>Hello User, </h1> <p>Welcome to {$amount}</p>";
    }else{
        response(NULL, NULL, 200,"No Record Found");
        }
}else{
    response(NULL, NULL, 400,"Invalid Request");
    }

function response($order_id,$amount,$latitude,$longitude){
    $response['order_id'] = $order_id;
    $response['amount'] = $amount;
    $response['latitude'] = $latitude;
    $response['longitude'] = $longitude;
    
    $json_response = json_encode($response);
    echo $json_response;

    
}
?>
 

mihe7

Top Contributor
Welcher Eintrag kommt denn da raus? mit diesem Befehl?
Irgendeiner - vermutlich der erste, denn 1=1 ist immer wahr. Man könnte ja mal den mit dem höchsten Wert ermitteln:


und so könnte man jetzt die table droppen?
Ja, dazu kannst Du versuchen, ein 0; DROP TABLE CO2Data zu senden, damit aus dem SQL-String etwas wie SELECT * FROM `CO2Data` WHERE ID=0; DROP TABLE CO2Data wird. Kann sein, dass man das etwas komplizierter anstellen muss, aber das Prinzip ist klar.

Dachte ich auch, bis ich die Page, also HTML Code einbauen wollte, das klappte irgendwie nicht...
Soll der Link eine HTML-Seite aufrufen? Dann musst Du einfach im PHP-Skript der Seite den $GET-Parameter auswerten.
 

izoards

Bekanntes Mitglied
oll der Link eine HTML-Seite aufrufen? Dann musst Du einfach im PHP-Skript der Seite den $GET-Parameter auswerten.
Ja genau, der Link soll eine HTML seite darstellen..
zur Zeit mache ich es über ein Eingabefeld, welches dann die api/72 anfrage macht 🤷‍♂️


Also analog dem tutorial, eigentlich will ich direkt die anzeige ohne manuelle eingabe, aber eben, konnte irgendwie kein html im obigen php code einbinden 🙁
 

mihe7

Top Contributor
Dafür bräuchtest Du noch nicht mal eine REST-API, einfach den $GET-Parameter im PHP-Skript auswerten (z. B. in einer Datei test.php)
PHP:
<html>
...
<body>
<?php
if (isset($_GET['ID']) && $_GET['ID']!="") {
    include('config.php');
$order_id = $_GET['ID'];
$result = mysqli_query(
$con,
"SELECT * FROM `CO2Data` WHERE ID=$order_id");
if(mysqli_num_rows($result)>0){
$row = mysqli_fetch_array($result);
$amount = $row['Wert'];
$latitude = $row['Latitude'];
$longitude = $row['Longitude'];
?>
<div><?php echo $amount; ?></div>
<div><?php echo $latitude; ?></div>
<div><?php echo $longitude; ?></div>
</body>
</html>

Natürlich könntest Du das auch per REST-API machen:

HTML:
<html>
...
<body>
<div id="amount"></div>
<div id="lat"></div>
<div id="lon"></div>

<script>
let query = document.location.search;
fetch("http://zusellipi.ddns.net/api.php" + query).then(r => r.json()).then(data => {
    document.getElementById("amount").innerText = data.amount;
    document.getElementById("lat").innerText = data.latitude;
    document.getElementById("lon").innerText = data.longitude;
});
</script>
</body>
</html>
Wenn Du den Code in eine HTML-Datei wirfst, werden beim Anzeigen der Seite
  1. Anfrageparameter (z. B. ?ID=72) an die URL http://zusellipi.ddns.net/api.php gehängt,
  2. eine GET-Anfrage durchgeführt,
  3. das JSON ausgewertet und
  4. die Werte in die betreffenden HTML-Elemente übertragen.
 

izoards

Bekanntes Mitglied
Wenn Du den Code in eine HTML-Datei wirfst, werden beim Anzeigen der Seite
  1. Anfrageparameter (z. B. ?ID=72) an die URL http://zusellipi.ddns.net/api.php gehängt,
  2. eine GET-Anfrage durchgeführt,
  3. das JSON ausgewertet und
  4. die Werte in die betreffenden HTML-Elemente übertragen.

Oh top :) Vielen Dank.

https://www.php.net/manual/de/mysqli-stmt.bind-param.php hat gesagt.:

PHP:
$stmt = $mysqli->prepare("INSERT INTO CountryLanguage VALUES (?, ?, ?, ?)");
$stmt->bind_param('sssd', $code, $language, $official, $percent);
Vielen Dank, das probiere ich demnächst umzusetzen :)

Irgendwie klappt das bei mir noch nicht mit dem prepared statement.
Hier mein Versuch, ich kriege ein HTTP ERROR 500

PHP:
<?php
//https://www.allphptricks.com/create-and-consume-simple-rest-api-in-php/ok
header("Content-Type:application/json");
if (isset($_GET['ID']) && $_GET['ID']!="") {
    include('config.php');
    
    mysqli_connect($con);
    
    $order_id = $_GET['ID'];
    $stmt = $mysqli->prepare('SELECT * FROM `CO2Data` WHERE ID = ?');
    $stmt->bind_param('i', $order_id);*/
    $stmt->execute();
    $result = $stmt->get_result();


    if(mysqli_num_rows($result)>0){
        $row = mysqli_fetch_array($result);
        $amount = $row['Wert'];
        $latitude = $row['Latitude'];
        $longitude = $row['Longitude'];
        response($order_id, $amount, $latitude,$longitude);
        mysqli_close($con);
    }else{
        response(NULL, NULL, 200,"No Record Found");
        }
    }else{
        response(NULL, NULL, 400,"Invalid Request");*/
        }

function response($order_id,$amount,$latitude,$longitude){
    $response['order_id'] = $order_id;
    $response['amount'] = $amount;
    $response['latitude'] = $latitude;
    $response['longitude'] = $longitude;
    
    $json_response = json_encode($response);
    echo $json_response;
}
?>
 

izoards

Bekanntes Mitglied
In diesem Fall habe ich leider kein Entwicklungssystem... Ich entwickle zur Zeit in Produktion mit Notepadd++
Wäre hier Webstorm von IntelliJ das richtige? Oder PHPStorm?
 

KonradN

Super-Moderator
Mitarbeiter
In diesem Fall habe ich leider kein Entwicklungssystem... Ich entwickle zur Zeit in Produktion mit Notepadd++
Wäre hier Webstorm von IntelliJ das richtige? Oder PHPStorm?
Das kann ich absolut nicht nachvollziehen. Du brauchst doch eine Entwicklungsumgebung. Das kann ja einfach Deein Rechner sein.

Da kannst Du Dir ja einen Webserver mit php drauf packen ... und die Datenbank und was Du sonst so brauchst. Da gibt es dann Lösungen wie XAMPP: https://www.apachefriends.org/de/index.html

Und da geht es nicht um einen Editor. Klar - auch da würde ich nie Notepad++ verwenden sondern eine richtige Entwicklungsumgebung, aber das spielt jetzt hier keine Rolle. Hier ist der Kernpunkt ja, dass Du einfach nur eine 500 bekommst und keinerlei Meldungen, was denn schief gelaufen ist. (Wobei das vermutlich in einem Logfile zu finden wäre.)
 

KonradN

Super-Moderator
Mitarbeiter
Die Hardware ist egal. Es geht um die Konfiguration:
  • Produktion = Es greifen Kunden darauf zu. Das Teil wird produktiv genutzt. Da dürfen dann keine Details kommen, was schief gelaufen ist. Statt dessen kommt nur 500 Server Error.
  • Entwicklung = Da sind keine Kunden drauf. Das sehen nur die Entwickler. Da sollen dann also so viele Details kommen wie nur möglich.

Du hast in Deinem PHP Script einen Fehler und bekommst nur das 500. Du willst aber doch wissen, was falsch gelaufen ist. Daher brauchst Du eine andere Konfiguration (in der SO Antwort sind die Schalter benannt).

Oder Du schaust einfach mal in die Logfiles, was Du da so findest.
 

izoards

Bekanntes Mitglied
Ich habs geschafft, ich glaube das Problem war beim auslesen der Datenbankanfrage, so wie es zur Zeit ist und läuft:

PHP:
<?php
//https://www.allphptricks.com/create-and-consume-simple-rest-api-in-php/ok
header("Content-Type:application/json");
if (isset($_GET['ID']) && $_GET['ID']!="") {
    include('config.php');
    $order_id = $_GET['ID'];
    
    mysqli_connect($con);
    
    
    $stmt = $con->prepare("SELECT * FROM `CO2Data` WHERE ID=?");
    $stmt->bind_param('i', $order_id);
    $stmt->execute();
    $result = $stmt->get_result();
    /* Get the number of rows */
    $num_of_rows = $result->num_rows;

    if ($num_of_rows>0) {
    while ($row = $result->fetch_assoc()) {
        $amount = $row['Wert'];
        $latitude = $row['Latitude'];
        $longitude = $row['Longitude'];   
    }
    response($order_id, $amount, $latitude,$longitude);
    mysqli_close($con);
    
    
    }else{
        response(NULL, NULL, 200,"No Record Found");
        }
    }else{
    response(NULL, NULL, 400,"Invalid Request");
    }



function response($order_id,$amount,$latitude,$longitude){
    $response['order_id'] = $order_id;
    $response['amount'] = $amount;
    $response['latitude'] = $latitude;
    $response['longitude'] = $longitude;
    
    $json_response = json_encode($response);
    echo $json_response;

    
}
?>

Vielen Dank für die Unterstützung @mihe7 und @KonradN
Eine Entwicklungsumgebung mit Testsystem und anständigen Fehlermeldungen wäre sicherlich produktiver.
 

Ähnliche Java Themen

Neue Themen


Oben