Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: JavaScript, PHP: parametrin välittäminen Ajaxilla

SMK79 [08.02.2020 11:35:08]

#

Yritän välittää Ajaxilla parametrin PHP:lle SQL-kyselyyn, mutta SQL ei jostain syystä tunnista hakutekijää. Osaisiko joku sanoa mikä alla olevassa on pielessä?
Homma pelittää, jos määritän iduutisen numerolla esim. '1', mutta tuo lähetetty parametri ei tunnu välittyvän kyselylle.

Tuo elementin ID on ylempänä määritelty näin: id='uutinen".$rivi->iduutinen."'

Ajax

function kokouutinen(iduutinen) {
  var xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
     document.getElementById("uutinen"+iduutinen).innerHTML = this.responseText;
    }
  };
  xhttp.open("GET", "luekokouutinen1.php?uutinen="+iduutinen, true);
  xhttp.send();
}

PHP

$uutisenid=$_GET[”uutinen”];

$tulos=mysqli_query($yhteys, "SELECT teksti FROM uutinen WHERE iduutinen=$uutisenid");

while ($rivi = mysqli_fetch_object($tulos)){
	print $rivi->teksti;
}

Grez [08.02.2020 12:17:38]

#

Tuosta nyt pistää heti silmään että koodissa on SQL injektio. Eli karkeasti voisi sanoa, että kuka tahansa sivujen käyttäjä voi tehdä tietokannallasi mitä haluaa, eli vaikkapa lukea ylläpitäjät taulun (jos siellä on sellainen) sisällön ja lisätä sinne itsensä. Palvelimen päässä ei koskaan saa luottaa että selaimen päästä tulee vain odotetunlaisia pyyntöjä.

Yleisesti ottaen suosittelen parametrisoitujen kyselyiden käyttöä, joka tässäkin tapauksessa olisi estänyt injektion.

Sitten itse kysymykseesi, niin koodissa ei näytetä miten kutsut tuota kokouutinen -funktiota. Vika voisi olla siinä.

Metabolix [08.02.2020 12:32:23]

#

Virheiden etsinnässä auttaa, jos kun laittaa virheilmoitukset näkyviin oppaan mukaisesti.

Kuten värityksestä näkyy, yksi virhe on siinä, että PHP-koodin alussa on lainausmerkkeinä ”-merkkejä eikä "-merkkejä. Tällöin SQL-kyselyyn ei välity kyseistä arvoa ollenkaan.

Kuten Grez sanoikin, koodista ei käy ilmi, miten ”tuo elementin id” välittyy funktiolle. Jos parametri iduutinen sisältää tosiaan tekstin "uutinen1", niin silloinhan tästä pitäisi karsia "uutinen" pois, jotta jäljelle jäisi pelkkä numero kyselyä varten.

Lisäksi koodissa on vakava SQL-aukko, nimittäin et käsittele parametria mitenkään, joten hakkeri voi hakea tuolla PHP-sivulla tietokannastasi aivan mitä tahansa tietoa mistä tahansa taulusta.

Ylipäänsä XMLHttpRequest on hieman vanhanaikainen tapa tähän. Fetch API on käytännöllisempi.

Tässä on kokonainen toimiva koodi, josta voit soveltaa.

<?php
// Yksinkertaisuuden vuoksi koko uutisen haku on tässä samassa tiedostossa.
$kokouutinen = intval($_GET["kokouutinen"] ?? 0);
if ($kokouutinen) {
  // TODO: Tee tietokantahaku id:llä $kokouutinen.
  echo "<p><em>Jee!</em> Pyydettiin koko uutinen id:llä {$kokouutinen}.</p>";
  exit();
}

// Tässä on testausta varten valeuutinen.
$rivi = (object)["uutinenid" => 123];
?>
<!DOCTYPE html>
<meta charset="UTF-8">

<!-- Uutiselle tarvitaan id, ja linkkiin laitetaan myös id. -->
<div id="uutinen-<?= intval($rivi->uutinenid) ?>">
  <a href="#lisää" class="uutinen-lue-lisää" data-uutinen-id=<?= intval($rivi->uutinenid) ?>>Lue lisää!</a>
</div>

<script>
// Uutisen lataus tehdään asynkronisesti fetch-funktiolla.
async function lataaUutinen(id) {
  let f = await fetch("?kokouutinen=" + id);
  document.getElementById("uutinen-" + id).innerHTML = await f.text();
}
// Klikkaus laittaa uutisen latautumaan, id saadaan data-attribuutista.
function hoidaUutinenLueLisääClick(e) {
  e.preventDefault();
  lataaUutinen(this.dataset.uutinenId);
}
// Laitetaan yllä oleva käsittelijä latauslinkeille.
for (const a of document.querySelectorAll(".uutinen-lue-lisää")) {
  a.addEventListener("click", hoidaUutinenLueLisääClick);
}
</script>

Grez [08.02.2020 12:38:28]

#

Kappas, en tosiaan huomannut noita vääriä lainausmerkkejä, vaikka katsoinkin että kummallisen näköiset.

SMK79 [08.02.2020 13:12:48]

#

Kiitos vinkeistä, kokeilen auttaisiko noiden lainausmerkkien muokkaus, mielestäni ne on kaikkialla kirjoitettu samoilla näppäimillä, mutta tarkistan. Tässä on kyse koulutehtävästä, jota haluaisin nyt viikonloppuna edistää, enkä saa vinkkejä/kommentteja opettajalta ennen maanantaita. En pääse hommassa eteenpäin ennenkuin saan tuon parametrin toimimaan.

Funktiota kutsutaan Button onclickillä kokouutinen(".$rivi->iduutinen.");

Lisäys: Kiitos, tuo lainausmerkkien korjaus auttoi ja koko uutisen lukeminen toimii nyt jokaiselle uutiselle erikeen id:n mukaan :)

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta