Avatar billede Slettet bruger
08. juli 2012 - 16:50 Der 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?


På forhånd tak.
Avatar billede 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 ;
Avatar billede olebole Juniormester
08. juli 2012 - 17:00 #2
<ole>

Prøv at kikke på htmlentities

/mvh
</bole>
Avatar billede Slettet bruger
08. juli 2012 - 17:18 #3
Tak.

Det ser ikke ud til at fungere på et array, som fx:
print_r(htmlentities($_POST, ENT_QUOTES));

Og jeg kan ikke umiddelbart finde en løsning i dokumentationen. Jeg kan kun gøre det på hvert enkelt element, som:
htmlentities($_POST['name'], ENT_QUOTES);


Jeg tænker på at holde mig til str_replace, da den godt kan køres på et helt array og ramme hver enkelt værdi, som fx:
print_r(str_replace(" \ " " , " & quot ; " , str_replace( " ' " , " & #39 ; " , $_POST)));

Vil dette mon være den smarteste måde? Selvom jeg skal manuelt indtaste entities for hvert tegn.
Avatar billede Qobra Nybegynder
08. juli 2012 - 17:37 #4
prøv: print_r(array_map("htmlentities", $_POST))
Avatar billede Qobra Nybegynder
08. juli 2012 - 17:44 #5
Eller nok nærmere sådan her, hvis du har multidimensionelt, og skal have ekstra argument på htmlentities:

<?php
function test_escape(&$item, $key)
{
    $item = htmlentities($item, ENT_QUOTES);
}
array_walk($_POST, 'test_escape');
print_r($_POST);
?>
Avatar billede Qobra Nybegynder
08. juli 2012 - 17:46 #6
Skulle have været array_walk_recursive i stedet for bare array_walk.
Avatar billede olebole Juniormester
08. juli 2012 - 17:58 #7
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  =)
Avatar billede 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.)

@Qobra
Tak, jeg prøver lige med det.
Avatar billede Qobra Nybegynder
08. juli 2012 - 18:12 #9
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.
Avatar billede olebole Juniormester
08. juli 2012 - 18:20 #10
[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  =)
Avatar billede olebole Juniormester
08. juli 2012 - 18:26 #11
#8: Jeg forstår ikke, hvorfor du har problemer med apostroffer og gåseøjne. I hvilken forbindelse opstår de problemer?
Avatar billede Qobra Nybegynder
08. juli 2012 - 18:35 #12
#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.
Avatar billede olebole Juniormester
08. juli 2012 - 19:10 #13
*LoL* Nej, måske gætter du ikke, men i så fald synes jeg, du er usammenhængende i din argumentation  :D

Hvad er forskellen på at huske at escape før - og huske at escape efter? Er det ikke farligt at glemme at escape ved indsættelsen?
Avatar billede olebole Juniormester
08. juli 2012 - 19:51 #14
@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();
}
?>

<div>
<?php
if (isset($db)) {
    $sql = 'SELECT `myfield` FROM `mytest`';
    $res = $db->query($sql);
    while ($row=$res->fetch_assoc()) {
        echo '<p>'.$row['myfield'].'</p>';
    }
    $res->free();
    $sql = 'DROP TABLE `mytest`';
    $db->query($sql);
    $db->close();
}
?>
</div>

<form action="" method="post">
    <p><input name="mytext[]" type="text"></p>
    <p><input name="mytext[]" type="text"></p>
    <p><input name="mytext[]" type="text"></p>
    <p><input name="mytext[]" type="text"></p>
    <p><button type="submit">TEST</button></p>
</form>


</body>
</html>

Derfor ville det være hensigtsmæssigt, om du fortalte, hvor det er, der opstår problemer  =)
Avatar billede Qobra Nybegynder
08. juli 2012 - 19:51 #15
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.
Avatar billede olebole Juniormester
08. juli 2012 - 20:03 #16
Det kan med andre ord være fatalt at:

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.
Avatar billede Qobra Nybegynder
08. juli 2012 - 20:15 #17
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.
Avatar billede olebole Juniormester
08. juli 2012 - 21:09 #18
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)
Avatar billede Qobra Nybegynder
09. juli 2012 - 21:30 #19
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 :-)
Avatar billede Qobra Nybegynder
09. juli 2012 - 21:56 #20
Mon ikke der er svaret nok på denne tråd til at der skal lukkes? Håber du kunne bruge det.
Avatar billede olebole Juniormester
09. juli 2012 - 22:42 #21
#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)
Avatar billede Qobra Nybegynder
10. juli 2012 - 00:51 #22
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 :)
Avatar billede olebole Juniormester
10. juli 2012 - 02:09 #23
Du husker også elendigt! Læs, hvad du skriver:

"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  =)
Avatar billede Qobra Nybegynder
10. juli 2012 - 08:07 #24
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.
Avatar billede olebole Juniormester
10. juli 2012 - 15:33 #25
*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)
Avatar billede Qobra Nybegynder
10. juli 2012 - 15:51 #26
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.
Avatar billede olebole Juniormester
10. juli 2012 - 16:19 #27
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 ...?!??!!!
Avatar billede 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.
Avatar billede olebole Juniormester
05. august 2012 - 17:20 #29
Ellers tak, jeg samler ikke point  =)

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'  =)
Avatar billede Ny bruger Nybegynder

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.

Loading billede Opret Preview
Kategori
Vi tilbyder markedets bedste kurser inden for webudvikling

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester



IT-JOB

Metro Service A/S

Risk & Cyber Security Expert

Udviklings- og Forenklingsstyrelsen

Data engineer til cloud-baseret dataplatform

Vive - Det Nationale Forsknings- og Analysecenter for Velfærd

Erfaren datamanager med registerkompetencer

Udviklings- og Forenklingsstyrelsen

Erfaren teamleder til årsopgørelsen

Udviklings- og Forenklingsstyrelsen

Infrastrukturspecialist til tværfagligt team