Miten kannattaisi hoitaa foorumin yksityisviestien ja threadien tallentaminen? Mietitään aluksi vaikka nuo yksityisviestit :)
Kannattaako jokaista käyttäjää kohden tehdä taulukko, missä on viestin lähettäjä, viesti, lähetys aika, tieto että onko viesti luettu (eli onko uusi vai ei) jne. ? Vai voiko jotenkin tehdä "2 ulotteisia" taulukoita, eli että "käyttäjät" taulukossa olisi yhtenä kohtana ikäänkuin toinen taulukko, jossa olisi sitten nuo yksityisviestien tiedot..
Tämä kun selviää, niin eiköhän nuo threadienkin tallentaminen onnistu.
Oletettavasti normaalit viestit ja yksityisviestit eroavat sarakkeiltaan kuitenkin sen verran, että lienee fiksuinta tehdä oma yksityisviestit-taulu, jossa sitten tarvittavat kentät, kuten lähettäjän id ja vastaanottajan id. Ei siis monta taulua yksityisviesteille, vaan ainoastaan tuo yksi.
Ainiin, nyt hogasin :)
Onlin alunperinkin tekemässä erikseen noita yksityisviestejä ja itse foorumin viestejä. Tajusin juuri, että käyttäjien yksityisviestit voivat olla sulassa sovussa samassa taulukossa, koska voin aina valita niistä vain ne, jotka on lähetetty jollekkin tietylle henkilölle..
... WHERE saaja = $user; :)
eiköhän se tästä. pitäisi varmaan etukäteen hieman suunnitella noita taulukoita, ettei jälkeen päin tarvitse ruveta muuttelemaan.
Itse varmaan pistäisin ne yksityisviestit kuitenkin omaan tauluun. Olisi mielestäni ihmisellekin selkeämpi hahmottaa sitten niiden taulujen sisältö, kun yksi taulu sisältää vain yhdenlaista tietoa.
Ja muistathan käyttää sitten id:itä tallentamiseen (viitaten tuohon esimerkkiisi), varmaan oletkin laittamassa niin, mutta painotan silti. Itse tein yhden vanhan (yhä aktiivisessa käytössä olevan tosin) projektin taulut tyhmästi, kun en käyttänyt niitä id:itä (eli avaimia), vaan esimerkiksi uniikkeja käyttäjinimiä... Nyt onkin edessä sitten melkoisen massiivinen muunnosoperaatio, jäänyt sen verran vaivaamaan, että pakkohan se on tehdä järkevämmin tässä jossain vaiheessa...
"Itse varmaan pistäisin ne yksityisviestit kuitenkin omaan tauluun."
Tarkoitatko, että jokaiselle käyttäjälle luotaisiin oma taulu yksityisviestejä varten? Tuskin.. Nyt on siis käytössä taulut "users" ja "yv", kun yksityisviestit pelittävät, niin teen vielä taulun "foorumi".
Onko siitä jotain haittaa, että viittaa käyttäjiin niide nimillä, kun kuitenkin ovat uniikkeja? Niille tulee kyllä myös id, joilla niihin viitataan esim. yksityisviestejä lähetettäessä, mutta aina välillä viittaan käyttäjien nimillä.
Onko turvallista hakea yksityisviestit näin:
$res = mysql_query("SELECT id, lahettaja, saaja, otsikko, pvm, luettu, vastattu FROM yv WHERE saaja = '".$_SESSION['user']."' AND poistettu=0");
Mietin lähinnä, että onko helppo käyttäjän helppo muokata tuota $_SESSION muuttujaa siten, että $_SESSION['user'] palauttaisi jonkun muun käyttäjän?
Sessioon on tallennettu sisään kirjautuneen käyttäjän nimi ja id..
Kun jollekkin lähetetään yv, niin käyttäjä viittaa häneen tietysti käyttäjänimellä, eikä id:llä. Pitäisikö tästä huolimatta muuttaa tuo käyttäjänimi sitten id:ksi, joka tallennettaisiin tuohon "saaja" kohtaan? Mitä käytännön hyötyä siitä olisi?
msdos464 kirjoitti:
"Itse varmaan pistäisin ne yksityisviestit kuitenkin omaan tauluun."
Tarkoitatko, että jokaiselle käyttäjälle luotaisiin oma taulu yksityisviestejä varten? Tuskin.. Nyt on siis käytössä taulut "users" ja "yv", kun yksityisviestit pelittävät, niin teen vielä taulun "foorumi".
Ei vaineskaan, kun juuri noin että kaikille yksityisviesteille on yksi taulu ja normiviesteille toinen.
msdos464 kirjoitti:
Onko siitä jotain haittaa, että viittaa käyttäjiin niide nimillä, kun kuitenkin ovat uniikkeja? Niille tulee kyllä myös id, joilla niihin viitataan esim. yksityisviestejä lähetettäessä, mutta aina välillä viittaan käyttäjien nimillä.
Sitten kun niitä rupeaa olemaan paljon niin varmasti se vähäsen hidastaa, ja sekavaakin käyttää molempia. Vie enemmän tilaakin kannasta merkkijono kuin yksi luku :P
msdos464 kirjoitti:
Onko turvallista hakea yksityisviestit näin:
$res = mysql_query("SELECT id, lahettaja, saaja, otsikko, pvm, luettu, vastattu FROM yv WHERE saaja = '".$_SESSION['user']."' AND poistettu=0");
Mä eskapoisin tuon $_SESSION["user"]:n.
Teknisesti käyttäjinä kannattaa käyttää aina id-numeroita. Sivulle tulostaessa sitten skripteille (esim. linkeissä ?user=id) kerrotaan id, käyttäjälle taas tekstimuotoinen.
Sessiomuuttujia voi muokata vain jos käyttäjällä on pääsy palvelimelle ja oikeudet muokata PHP:n tallentamia sessiotiedostoja, joten melko turvallinen tapa tuo on.
Ja viittaukset toisiin tauluihin kannattaa lähes aina tehdä numeerisin sarakkein, eli siis id on parempi kuin nimi.
msdos464 kirjoitti:
Pitäisikö tästä huolimatta muuttaa tuo käyttäjänimi sitten id:ksi, joka tallennettaisiin tuohon "saaja" kohtaan? Mitä käytännön hyötyä siitä olisi?
Numeerinen kenttä on nopeampi etsiä (varsinkin, jos se on indeksi) ja lisäksi nuo nyt vaan on rumia nuo skandit ja välilyönnit tuolla osoiterivillä:
?user=%E4iti%20ja%20is%E4 versus ?user=100;
ajv kirjoitti:
msdos464 kirjoitti:
Pitäisikö tästä huolimatta muuttaa tuo käyttäjänimi sitten id:ksi, joka tallennettaisiin tuohon "saaja" kohtaan? Mitä käytännön hyötyä siitä olisi?
Numeerinen kenttä on nopeampi etsiä (varsinkin, jos se on indeksi) ja lisäksi nuo nyt vaan on rumia nuo skandit ja välilyönnit tuolla osoiterivillä:
?user=%E4iti%20ja%20is%E4 versus ?user=100;
Osoiterivillä viitataan käyttäjiin aina id:illä. Tuolla käyttäjänimellä viitataan oikeastaan ainoastaan yksityisviestejä käsitellessä.. No ehkä se silti kannattaa tehdä heti alusta asti kunnolla, vaikka tuo foorumi tuskin tulee koskaan mitään testausta laajempaan käyttöön :)
Relaatioita kuvatessa (siis esim. että tämä yksityisviesti menee käyttäjälle se ja se) tulisi aina käyttää niitä indeksejä, koska indekseillä tietojen hakeminen taulusta on mielettömästi nopeampaa kuin ei-indekseillä hakeminen (juuri sitä varten ne indeksit ovat, että niitä käytetään tietojen hakemiseen ja tietoihin viittaamiseen aina kun mahdollista).
Voithan toki tehdä niistä käyttäjänimistäkin indeksejä (kerta ne ovat uniikkeja), mutta ne tosiaan varaavat sitten paljon enemmän muistia kuin ne numeeriset indeksit.
Ja tarkoitin tuon tauluasian kuten soodakin sanoi, että kaikki yksityisviestit yhteen tauluun, ja kaikki muut viestit toiseen tauluun.
Id:n käytössä on sekin hyöty, että jos keskustelija haluaa myöhemmin muuttaa nimeään, yksi muutos tietokantaan riittää.
Jos viesti näkyy myöhemmin sekä lähettäjälle että vastaanottajalle, se voi muuten olla monella tavalla "poistettu".
Antti Laaksonen kirjoitti:
Id:n käytössä on sekin hyöty, että jos keskustelija haluaa myöhemmin muuttaa nimeään, yksi muutos tietokantaan riittää.
Jos viesti näkyy myöhemmin sekä lähettäjälle että vastaanottajalle, se voi muuten olla monella tavalla "poistettu".
Ihan totta muuten.
Mitenkäs nuo käyttäjältä saatavat syötteet.. millä ne pitäisi koodata, jotta SQL Injectionilta vältytään? mysql_real_escape_string ei taida riittää (ainakaan php.net:in mukaan) Tähän liittyen joku tietäisi varmaan jonkun hyvän linkin..
mysql_real_escape_string pitäisi mielestäni riittää. En nyt itse keksi miten tuon läpi ajetulla datalla injektion saisi aikaan (enkä jaksa kyllä noita kommentejakaan kahlata lävitse)...
Nyt yv:t rupeaa olemaan hanskassa.. seuraavaksi siis itse foorumin kimppuun. Miten siinä kannattaisi nuo taulukot toteuttaa, kun noita foorumin "tasoja" on useita:
* koko foorumi (näkyy eri aihealueet)
* aihealue (näkyy eri threadit)
* threadi (näkyy eri viestit)
Näihin kaikkiin tulisi kuitenkin käyttää yhtä ja samaa taulua? Jokaisesta viestistä ajattelin tallentaa (ainakin) nämä tiedot:
viestin id, lähettäjän id, threadin id, alueen id, lähetys pvm, otsikko, viesti, poistettu
Voiko tuollaisesta taulukosta helposti hakea kaikki eri aihealueet? Lisäksi tarvitaan näemmä Ainakin yksi table, jolla liitetään aihealueiden id:t niiden teksimuotoiseen nimeen ("Yleistä keskustelustelua" jne.)
Aihealueet yhteen tauluun, threadit yhteen tauluun, viestit yhteen tauluun, yksityisviestit yhteen tauluun... Eli kaikille erityyppisille tiedoille oma taulu.
JTS kirjoitti:
mysql_real_escape_string pitäisi mielestäni riittää.
Riittää mikäli tieto tulee ' tai " merkkien sisään, muuten on mahollista alikyselyt jne...
Esim
$_GET['id'] = '121221 OR id > 0'; DELETE FROM viestit WHERE id = mysql_real_escape_string($_GET['id'])
Kannattaa lukasta http://shiflett.org/php-security.pdf joskin SQL Injectiosta ei paljoa juttua, mutta muuten hyödyllistä.
Opiskelija kirjoitti:
JTS kirjoitti:
mysql_real_escape_string pitäisi mielestäni riittää.
Riittää mikäli tieto tulee ' tai " merkkien sisään, muuten on mahollista alikyselyt jne...
Hmm.. kun noita id:itä käyttää, niin ei niitä tullut laitettua lainausmerkkeihin... no tällä hetkellä ei ole mitään escapea, joten täytynee tehdä nuo molemmat muutokset kun ehtii.
edit: heh.. tällä hetkellä yksityisviestiin voi laittaa vaikka tämän:
<script> while (true) alert(); </script>
vaatii vähän parsintaa :P
msdos464 kirjoitti:
Hmm.. kun noita id:itä käyttää, niin ei niitä tullut laitettua lainausmerkkeihin... no tällä hetkellä ei ole mitään escapea, joten täytynee tehdä nuo molemmat muutokset kun ehtii.
Tietenkin voit katsoa että id on todellakin numero esim
https://www.php.net/manual/fi/function.intval.
https://www.php.net/manual/fi/function.is-numeric.php
Tai vaikka castata sen numeroksi:
<?php $id = (int) $_GET['id']; ?>
Tyyppimuunnos vaatii enemmän resursseja tulkilta sekä kannalta kun pukataan turhaa kyselyä jos id:ksi on annettu vaikkapa "10 kalaa narulla" tms.
Aihe on jo aika vanha, joten et voi enää vastata siihen.