Okay het lijkt me leuk wat meer uit te knobbelen mbt URL validatie binnen formulieren.

Het gaat me om een variant van het script uit het volgende topic.

http://www.phphulp.nl/php/forum/topic/5-invoervelden-tegelijk-verwerken-in-mysql-dbase/98031/

voor de duidelijkheid heb ik variabelen een andere naam gegeven.

Ik zal het script met extra web validatie code hier herhalen:



<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>HTML sjabloon</title>
</head>

<?php 

$num = $_POST['aantal'];

// url valideren
	
	if (isset($_POST['webadres[]']) == true && empty($_POST['webadres[]']) == false) {
		$urlv = $_POST['webadres[]'];
		if (filter_var($urlv, FILTER_VALIDATE_URL) == true) {
			// Hier moet iets uitgevoerd worden zoals bijv. hoe data in het formulier moet. Is mij nu niet duidelijk.
			
			
		} else {
		echo 'Sorry URL input incorrrect' ;		}
	}



?>

<body>
<form action="index.php" method="post" accept-charset="UTF-8"><?php
for ($i=0; $i < $num; $i++) {
    ?><p>
        <label for="webadres_<?php echo $i ?>">veld <?php echo ($i + 1) ?></label>
        <input type="text" name="webadres[]" id="webadres_<?php echo $i ?>" value="" />
    </p><?php
}
?><p>
    <button type="submit">Save</button>
</p>
</form>


</body>
</html>




Het 1e probleem waar ik tegenaan loop is URL validatie van de waarde in name.

Name heeft als waarde webadres. Maar omdat ik met een lus werk gebruik ik webadres[] met brackets dus.

Mijn vraag is of dit kan?

Dan het tweede. De URL validatie maakt dat er een beslissing wordt genomen (if(filter_var( .... etc.
Van hier moeten de gegevens naar de database. Maar zonder URL validatie gaan ze ook naar de database.

Op welke manier kun je dit het beste aanpakken?
Die brackets betekent dat je meerdere waarden dan opvangt in een PHP-array.
Deze kan je dan per stuk doorlopen met een foreach() lus.
filter_var() retourneert (meestal) de gefilterde waarde als de controle "slaagt", en false als deze mislukt. Deze vergelijken met true is dus niet heel erg zinnig.

Verder is filter_var voor URL-validatie niet helemaal waterdicht.

Zoals met zoveel security-gerelateerde zaken moet je niet proberen alles op 1 plaatst dicht te timmeren. Werk met lagen.

Nog belangrijker dan het filteren van input is in dit geval wellicht het escapen van output bij het afdrukken. Het is eigenlijk zaak dat je dit altijd doet, tenzij je een hele speciale reden hebt om dit niet te doen.

Je moet het zo zien: als mensen het leuk vinden om onzin in te vullen, laat ze. Of stop er een login tussen. Zorg gewoon dat alle ongein onschadelijk wordt gemaakt als je deze afdrukt.

Wel iets om te overwegen:
Maar zonder URL validatie gaan ze ook naar de database.

Waar voer je dan precies deze controle voor uit? het valideren van gegevens en de opslag hiervan zouden echt twee aparte stappen moeten zijn, waarbij de tweede alleen uitgevoerd zou moeten worden als de eerste slaagt, en anders niet.

Maar ja, het valideren van een URL op correctheid is een lastige. Ik zou hier meer aandacht schenken aan output escaping en misschien moderatie, als het erg vaak voorkomt dat er onzin wordt ingevuld.
Ik zit te denken aan een functie om het in de database te schrijven maar dit is onbekend voor mij.

Het maken van een functie is te doen en ook het aanroepen, maar het is niet duidelijk wat de scope vervolgens is.

In deze situatie van het bovenstaande script denk ik erover om te kiezen voor een functie die op regel 17 zou komen te staan.

Volgens mij zijn er verschillende mogelijkheden maar weet niet hoe dit aan te pakken. Kun je de gefilterde variabele tijdelijk in een functie zetten (of is dat onlogisch?) en daarna mbv de SQL opdracht in de database wegschrijven.
In plaats van een eigen functie gebruiken: plaats daar je query en voer hem daar uit.
Dus nadat je [] hebt weggehaald in de regels erboven, het stuk in een foreach()-loop heb gezet, de validatie werkend hebt gemaakt.
En gebruik dan PDO of mysqli om het op te slaan in je database.


Je latere for($i....) is overbodig: gebruik foreach(). Dan heb je $num ook niet nodig, hoef je die ook niet te controleren etc.



Als je <input type="text" name="velden[]"> gebruik, zit alles in $_POST['velden'].
Hoe veel input-velden je ook hebt.

Toevoeging op 30/08/2015 09:30:30:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>HTML sjabloon</title>
</head>

<?php
// is er iets ingevoerd? Is het een array? Zijn er waarden?
if (isset($_POST['webadres']) AND is_array($_POST['webadres']) AND count($_POST['webadres']) > 0)
{
	// ga elk item langs, of dat er nu 1 of 100 zijn
	foreach ($_POST['webadres'] as $adres)
		if (filter_var($adres, FILTER_VALIDATE_URL) !== false)
		{
			// $adres is een geldige URL
			$query = "INSERT INTO tabel (kolomnaam, kolomnaam2) VALUES (" . $adres . ", " . $user_id . ")";
			$res   = mysqli_query($query);
			if ($res === false)
			{
				echo '<p class="fout">De url ' . $adres . ' kon <b>niet</b> worden opgeslagen.</p>';
			}
			else
			{
				echo '<p class="goed">De url ' . $adres . ' is <b>goed</b> opgeslagen.</p>';
			}
		}
		else
		{
			echo '<p class="fout>Dit is geen geldig adres: ' . $adres . '</p>';
		}
}
?>

<body>
   <form action="" method="post" accept-charset="UTF-8">
           <label for="webadres">Invoer: </label><input type="text" name="webadres[]" id="webadres" value="" /><br>
           <label for="webadres">Invoer: </label><input type="text" name="webadres[]" id="webadres" value="" /><br>
           <label for="webadres">Invoer: </label><input type="text" name="webadres[]" id="webadres" value="" /><br>
           <label for="webadres">Invoer: </label><input type="text" name="webadres[]" id="webadres" value="" /><br>
           <label for="webadres">Invoer: </label><input type="text" name="webadres[]" id="webadres" value="" /><br>
           <label for="webadres">Invoer: </label><input type="text" name="webadres[]" id="webadres" value="" /><br>
           <label for="webadres">Invoer: </label><input type="text" name="webadres[]" id="webadres" value="" /><br>
    <input type="submit">Save</input>
</form>
</body>
</html>

Eddy E op 30/08/2015 09:17:27



In plaats van een eigen functie gebruiken: plaats daar je query en voer hem daar uit.



<form action = ''> stuurt het naar een volgend script. Dit blijft zo.

de submit van dit formulier voert de SQL query uit in dat script.

Welke aanpak is dan mogelijk?
Vervolgens geeft Eddy je een redelijk volledig script, probeer dat eens uit?

De waarden zouden trouwens nog steeds te allen tijde ge-escaped moeten worden :].

Ja maar waar ik tegen aan loop is dat method post alleen de waarde die in name is opgegeven mee neemt.

Ik moet nu een nieuwe variabele maken. Ik zoek een php (of andere) manier om een extra variabele met form mee te submitten.
Welke variabele heb je nodig dan?
$_POST['webadres'] zal een array zijn met daarin alle velden.
Probeer eens uit wat ik heb gemaakt trouwens...

Ik ben door de posting van Thomas wel gaan nadenken over de manier van programmeren. Het schrijven van een goed script brengt met zich mee dat er geen verkeerde informatie zoals lege velden of kwaadaardige sql injectie (zegt me weinig eigenlijk) in de database moet komen.

Ik ben zelf niet gewend om te denken in lagen bij het maken van php/sql scripts (maar ik ben dan ook nog vrij nieuw in deze materie). Hoe moet ik het precies zien ?

Zijn er 1 of lagen of nog meer? Kun je eerst iets laten invoeren en daarna alle gebruikelijke validatie functies en mysql injectie afvangen in een apart script? Dat lijkt me redelijk handig en mochten er nieuwe gaten in beveiliging worden gevonden dan zet je die in dat specifieke script.

Dit zijn zo wat vragen die in je opkomen als je een goed en veilig script wilt maken.
>> Hoe moet ik het precies zien?

Het is eigenlijk het opbouwen van je applicatie in verschillende classes die zo hun eigen verantwoordelijkheden hebben. In plaats van in één keer van input naar output te gaan zonder maar een enkele functie gebruiken ga je dit in verschillende stappen doen.

De meest vuile methode is dit:
<?php
$name = $_GET['name'];
echo "Hi $name!";
?>
Leesvoer

Je maakt het stukken beter als je dit in stappen of lagen doet:
<?php

// Het gebruik van een Request class in plaats van direct $_GET of $_POST
$name = $request->get('name');

// input filtering
$filter = $this->container->get('some.filter');
$name = $filter->filterPlaintext($name);

// Het gebruik van een template met veilige HTML die we als output willen.
$template = new TemplateEngine();
echo $template->render("<html><body>Hi {{ name }}!</body></html>", array('name' => $name));
?>

De render functie krijgt twee variabelen mee.

1) de inhoud van de pagina ook wel template genoemd.
2) een associatieve array met variabelen die in de template vervangen moeten worden.
Voordat deze vervangen worden worden ze eerst escaped.

Het bovenstaande is een beetje ala het Symfony framework die gebruik maakt van de Twig template engine.

Wat ik maar wil zeggen is dit: Door een gedegen framework te gebruiken worden de meeste van dit soort security concerns voor je uit handen genomen. Hierdoor kun je je tijd besteden aan het bouwen van websites in plaats van aan "Het wiel opnieuw uitvinden" en beveiligingslekken dichten (en natuurlijk de schade herstellen die die lekken al aangericht hebben).

Reageren