08. juli 2012 - 16:50Der er
28 kommentarer og 1 løsning
Escaping html tegn i en databasestreng til deres entities
Jeg henter indholdet fra en tabel i en MySQL database og indsætter det rundt omkring i et html-dokument. Mit problem er, at der forekommer tegn som " og < og > og ' i det indhold, jeg henter, hvilket giver html-problemer.
Hvad er det smarteste at gøre ved dette? Hvordan laver jeg noget replace på al indholdet fra min mysql_query på én gang på samme tid i PHP? Jeg ønsker umiddelbart at udskifte til de tilsvarende entities sådan her:
< bliver til < > bliver til > " bliver til " ' bliver til '
En enkelt str_replace er jo nem, men hvis jeg ikke skal gøre det på hvert enkelt databasefelt, har jeg brug for at kunne gøre det på en hel flerdimensionel array, som man jo får fra mysql_query("SELECT * FROM ...."), der henter indholdet fra databasen.
Nu hvor jeg står med dette problem, har jeg tænkt en del over, hvordan det egentlig er smartest at gemme indhold i en database og hvornår der egentlig bør laves escapes og udskiftes til entities. Jeg gemmer i databasen ved at udfylde en formular på html-siden. Dernæst ved ajax (vha. jquery ved klik på submitknappen) sender jeg ved POST dataene til et PHP-script, der indsætter dette i databasen.
Jeg laver allerede en grundig escaping af specialtegn i jQuery'en vha. Regex:
data = data.replace(/([ !#$%'()*+,.\/:?@[\\\]^`{|}~])/g,'\\$1')
hvilket forhindrer, at der opstår problemer undervejs i gemmefasen. Men da tegnene naturligvis igen står som specialtegn i databasen bagefter, opstår problemet, når indholdet skal hentes ud derfra senere.
Så, hvor bør man egentlig lave sin entity-udskiftning af html-specialtegnene? I jQuery'en eller i PHP'scriptet der gemmer? I disse to tilfælde vil tegnene jo stå med entities i databasen, og så er det ikke den rene data, hvilket normalt ville være optimalt. Det virker dog alligevel mest logisk, da jeg kun skal bruge indholdet som tekst, men hvis jeg udskifter inden får jeg problemer med tegnene ; og & som entities'ne indeholder. Ellers skal der, som jeg spørger om ovenfor, først laves entities, når dataene hentes igen.
Hvad bør man og hvad virker? Og hvordan laver man en komplet replace i alt indhold i en multidimensionel mysql_query array i php?
Teknologi, AI og forretning er i centrum på Computerworlds Cloud og AI Festival i København d. 18. og 19. september. Se hele programmet for den store konference om strategisk brug af Cloud og AI på: www.cloud-festival.dk
Slettet bruger
08. juli 2012 - 16:52#1
Hehe, jeg kan se, at Ekspertens Preview-knap trods alt ikke viser præcis samme resultat, som når man poster. Ovenfor skulle der have stået, at tegnene, det drejer sig om, skal udskiftes til:
< bliver til & lt ; > bliver til & gt ; " bliver til & quot ; ' bliver til & #39 ;
Jamen, hvorfor vil du escape variablerne i POST array'et? Data i databasen må ikke være HTML-escaped. Data i databasen er data - ikke data, formateret efter en eller anden 'tilfældig' marjup standard.
I stedet formaterer du dine data, når du henter dem - og de skal vises på en HTML-side.
Fejlen er måske, at du i udgangspunktet ønsker at gemme HTML i databasen. Det kunne tyde på nogle uheldigt løste programmatiske designudfordringer =)
Synes godt om
Slettet bruger
08. juli 2012 - 18:07#8
@Olebole Mit spørgsmål går også halvvejs ud på, hvor smart det vil være at indkode til html entities inden der gemmes i databasen. Det har jeg IKKE gjort i øjeblikket. Jeg er klar over, at databaseindhold bør være uformateret. Jeg har problemer, når jeg henter de rå data, så " og ' osv. skal omkodes først, og mit spørgsmål drejer sig om, hvordan man gør det smartest.
(Mine eksempler med $_POST er bare eksempler, som jeg bruger til at teste på, når jeg har nogle nye php-kommandoer at undersøge.)
Jeg undrede mig også lidt, da det bliver mere besværligt at søge i databasen. Men det behøver dog ikke være en dårlig ide, da man kan få performance ved ikke altid at skulle escape html, og det er nok også mere sikkert bare at escape når man putter i, i stedet for altid at skulle huske at escape, når man tager ud og viser. Det er jo ikke tilfældig markup, det er data på den form det skal bruges.
[b]#9:[b] Man kan gøre præcis, hvad man vil. Det ændrer dog ikke ved, at det i udviklerkredse regnes for dårlig kodeskik at lægge formaterede data i databasen.
Jo, det er helt tilfældigt markup. Man må naturligvis ikke binde sig til at fremvise sine data på én måde. Hvad nu, hvis data på et tidspunkt skal syndikeres via en anden platform - Flash, f.eks?
"og det er nok også mere sikkert bare at escape når man putter i"
Ja, hvis man ikke ved det, kan man gætte på meget - men der må jeg så berolige dig. Der er ikke noget farligt ved sætte HTML-tags i databasen, eller at have dem liggende der. Til gengæld er det ikke særlig hensigtsmæssigt =)
#10: Jeg gætter ikke, det er farligt _ikke_ at have HTML i databasen: Lige for tiden er Cross-Site Scripting (XSS) er den helt store dille inden for hacking. Så derfor er det farligt, hvis man glemmer at escape, når man skal bruge det, men ikke farligt, hvis man altid husker det.
@steven: Jeg forstår som sagt ikke lige, hvad det er for problemer, du har med apostrof og/eller gåsøje. Hvis du f.eks. prøver denne fil, vil du ikke have problemer med de tegn:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>Untitled Document</title> </head> <body>
<?php if (!empty($_POST)) { // Ret denne linje til efter din opsætning $db = new mysqli('server','username','password','database');
$sql = 'CREATE TABLE IF NOT EXISTS `mytest` (`myfield` varchar(50)) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_danish_ci'; $db->query($sql); $sql = 'INSERT INTO `mytest` SET `myfield`=?'; $stmt = $db->prepare($sql); $stmt->bind_param('s', $val);
foreach ($_POST['mytext'] as $val) { $stmt->execute(); } $stmt->close(); } ?>
Det er selvfølgelig rigtigt :) Men ofte er der ikke så mange steder brugere kan lægge offentlige ting i en database, så der er mindre der skal huskes. Jeg vil heller ikke anbefale at lægge html i basen, men jeg synes ikke nødvendigvis det er en dårlig ide.
1) glemme at escape ikke-escaped HTML, når det hentes fra databasen
2) glemme at escape HTML, inden det lægges i databasen - emend det er marginalt lettere at huske
Den eneste begavede konklussion må derfor være: Det er alene på den baggrund en rigtig dårlig idé at lægge HTML i databasen. Derudover kommer så alle de andre rigtig gode grunde =)
Nu kan hele diskussionen i øvrigt være rystende ligegyldig i denne sammenhæng, da det har vist sig, det ikke er HTML, spørger har problemer med.
Der bliver faktisk spurgt til, hvordan data bør gemmes, og hvornår det bør escapes. Og når man i PHP i forvejen kører addslashes/magic_quotes på $_POST, for ikke at lave fejl, kan man lige så godt også bare køre htmlentities på. Så slipper man for både SQL injections og XSS, uden at skulle tænke. Personligt ville jeg som sagt ikke lægge HTML i databasen.
Ja, men der er jo ingen, der fobyder dig at følge med i tråden! I #8 fremgår det tydeligt, der ikke er tale om HTML-tags - men om apostroffer og gåseøjne.
Hvem i alverden kører dog 'addslashes/magic_quotes på $_POST' i 2012? Hvis du er interesseret i at slippe for SQL-injections, bruger du naturligvis prepared statements - enten, som jeg gjorde ovenfor, med MySQLI eller med PDO.
Det gamle MySQL-API er dybt forældet og i udgangspunktet fejlkonstrueret. Det er da også en af grundene til, at magic_quotes er deprecated.
Prøv aldrig at slippe under hegnet og undlade at tænke. Det er den sikreste måde at blive offer for et angreb på. Lær i stedet at kode tidssvarende med de seneste og forbedrede API'er *o)
Ole: Du ved lige så godt som jeg, at der stadig er masser, der bruger magic quotes, så det behøver vi vist ikke diskutere.
Steeven: Alting behøver jo ikke være best practice, så hvis du spørger mig kan du sagtens bare escape hele dit POST array og lægge html i basen. Hvis det virker for dig, så gør det. Det vigtigeste er, at det virker :-)
#19: Tværtimod! Hvis ingen længere brugte magic_quotes og addslashes, ville der ikke længere være grund til at diskutere dårlig praksis. Når der nu stadig er en hel del, der bruger det, kan der næppe findes bedre årsag til diskussionen.
Hvis man kikke Ekspertens (eller et hvilket somhelst andet PHP-forums) tråde igennem, vil det stå krystal klart for enhver, hvor store problemer denne praksis medfører.
@steeven: Hvis du derimod spørger en hvilken somhelst kompetent webudvikler, vil du blive rådet til at kode effektivt og sikkert og derfor (naturligvis) bruge prepared statements.
Det gamle MySQL-API er håbløst tåbeligt konstrueret - både langsomt og usikkert. Når nu MySQL er trådt ind i rækken af seriøse databaser, som understøtter parametriserede kald, ville det være komplet tåbeligt at nægte at tage imod denne hjælp fra teamet bag MySQL.
Det, jeg prøver at forholde mig til er, at der ikke er problemer med apostrof og/eller gåseøjne, når man behandler data rigtigt (lader databasen stå for at escape).
Det er netop, man bruger forældet escaping med f.aks. addslashes og magic_quotes, at der ofte opstår problemer med de tegn *o)
Det var ikke menigen jeg ville starte sådan en stor debat om sikkerhed, det var bare en sidebemærkning. Jeg anbefaler naturligvis ikke magic quotes, især fordi det ikke beskytter ordentligt mod injections. Prepared statements er en god teknik til at undgå, at din SQL bliver ændret. Sådan en god teknik er der ikke til HTML, så hvis du har ondsindet HTML i din database er det bare et spørgsmål om tid, før det bliver eksekveret - ligesom det er et spørgsmål om tid før man dummer sig med det gamle MySQL API. Derfor sagde jeg, at det er mere sikkert at escape inputtet med det samme. Så kommer man aldrig til at eksekvere ondsindet HTML ved en fejl. Og hvis du så en dag skifter væk fra HTML kan du heldigvis bare dekode HTMLen igen, så helt slemt er det vist ikke.
Jeg ved godt det ikke er best practice, men det virker, og nu gider jeg altså ikke diskutere det mere :)
"Der bliver faktisk spurgt til, hvordan data bør gemmes, og hvornår det bør escapes. Og når man i PHP i forvejen kører addslashes/magic_quotes på $_POST, for ikke at lave fejl, kan man lige så godt også bare køre htmlentities på. Så slipper man for både SQL injections og XSS, uden at skulle tænke"
Du tager det for givet, at "man i PHP [...] kører addslashes/magic_quotes på $_POST, for ikke at lave fejl", og bedyrer derefter, at "Så slipper man for SQL injections [...] uden at skulle tænke".
Det er helt fair, du efterfølgende har Googlet lidt og blevet klogere. Du behøver såmænd ikke blive stakåndet af at løbe som lyn og torden fra, hvad du skrev tidligere *o)
Det er dog kun én af de uheldige bivirkninger. HTML gør også data meget dårligt søgbare. Det betyder, man skal sløve databasen med LIKE og wildcards i de mest simple søgninger - og søgninger på sætninger bliver ekstremt elendige.
Men du har helt ret. Når noget er rigtig dårlig praksis, er det ikke best practice =)
Slap nu af Ole, sammenligningen med magic quotes skulle bare illustrere kvaliteten af at escape HTML i alt input - det er generelt ikke en ordentlig løsning. Det er tilgengæld hel fin praksis at gemme formatteret data, hvis du altid skal bruge det på den form. Man behøver ikke at følge alle mulige skoleeksempler, hvis man har en meget nemmere løsning.
*LoL* Det giver jo ikke mening at diskutere med en person, der ikke evner at læse, hvad han selv skriver - og konsekvent undlader at forholde sig til andres argumenter.
Du må sådan have de idéer, du har lyst til at have. Det eneste, jeg reagerer imod, er, når du prøver at få dårlig kodepraksis til at fremstå som noget, der betragtes som god kodepraksis i branchen.
Jeg er dog helt sikker på, at du bliver væsentligt klogere, hvis du - stik mod forventning - en dag skulle komme til at arbejde med webudvikling i et professionelt miljø. Men i mellemtiden ville det nok være hensigtsmæssigt at lytte lidt mere og ikke være så optaget af at kloge sig på noget, du tydeligvis ikke har den store viden om. Der er ikke spor galt i at have huller, hvor man kan lære noget *o)
Nu er jeg tilfældigvis IT konsulent, og laver i øjeblikket webudvikling hos en kunde. Hvem ved, måske sidder jeg lige nu og udøver dårlig kodepraksis, på netop din arbejdsplads? :-) Nogen gange har man bare ikke tid til best practice, og nogen gange er det fuldstændigt irrelevant hvordan et system/værktøj er kodet. Man må vurdere i det konkrete tilfælde, om best practice er nødvendigt. Jeg tror steeven har forstået hvad han skal gøre her, og så må han selv vurdere om han har behov for en sloppy løsning, en forkromet best practice løsning eller en mellemting.
Det må jeg indrømme, kommer oprigtig bag på mig! At du har opnået ansættelse i branchen, havde jeg aldrig haft fantasi til at forestille mig!
Jeg kan dog garantere, du ikke sidder i det firma, jeg arbejder i. I de firmaer, hvor jeg har arbejdet, var du aldrig sluppet gennem en ansættelsessamtale med de holdninger!
Alene det, at du kan tale om at "have behov for en sloppy løsning", forekommer mig fuldstændig uvirkeligt. Hvem i alverden har nogen sinde mødt et menneske, der havde ønsker eller behov for en sloppy løsning? Der er ved Gud ikke noget at sige til, branchen mange steder har et frygteligt dårligt ry!
"Nu skal de se Hr. Vi har helt sikkert lige den sloppy konstruerede bil, de har behov for - så de kan tage konen ud og se en sloppy produceret film ... naturligvis efter en sloppy middag, that is".
How pittyful can life be ...?!??!!!
Synes godt om
Slettet bruger
05. august 2012 - 01:11#28
@Olebole og @Qobra, tak for jeres svar. I deler pointene.
@Olebole, læg gerne et svar. Og tag hellere lidt frisk luft og en pause fra PC'en for en stund; personlige tilsvininger klæder ikke nogen.
Der er ikke tale om personlig tilsvining. Der er tale om, at jeg ikke bryder mig om, at man besudler mit fag. Det kan godt være, at personen er ansat som IT-konsulent, men det giver ikke hans udtalelser et mere professionelt snit.
Det kan ligeså godt være, han ikke er ansat som IT-konsulent. Vi har det bare fra en anonym bruger i et indlæg i et webforum - og fra en bruger, som i adskillige tråde har gjort sig til talsmand for i professionelle kredse overordentlig alternative holdninger.
Og hvad betyder betegnelsen 'IT-konsulent'? Har sådan én overhovedet forstand på webkode? Mig bekendt er det en betegnelse, man bruger for ansatte, man ikke ved, hvad man ellers skal kalde.
Jeg vil til enhver tid forbeholde mig retten til at forsvare mit fag og mine kollegaer mod sammenligning med fantaster. Det bør du ikke forveksle med 'personlig tilsvining' =)
Synes godt om
Ny brugerNybegynder
Din løsning...
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.