Hallo allemaal,

Dit is eerder een vraag om advies over veiligheid.
Ik merkte deze functies onlangs op:
$sanitized_a = filter_var($a, FILTER_SANITIZE_EMAIL);

Dus je kan input filteren tegen sql injectie bvb.

Nu vraag ik mij af of dit even veilig is om te gebruiken als de zelfgemaakte functies gelijk in wordpress.
Ozzie PHP op 29/12/2017 17:23:44

In zo'n geval zou ik misschien op een hoger niveau het IP-adres even willen blokkeren vanwege verdacht gedrag.


En dat is een goed voorbeeld van Value Objects. Je throwt een Exception, en in de catch log je iets, of je onderneemt een andere actie. Bij Value Objects kun je denken aan geldbedragen, datumbereiken, emailadressen, etc.
@Jan,

Maar dan moet dat value object wel weten welke waardes wel en niet zijn toegestaan. De toegestane waardes geef je dan als parameter mee in een array of zo?
@ Ozzie,

nee, de enige parameter(s) die je aan de constructor meegeeft, zijn de value(s) die je wilt gebruiken. De validatie vindt geheel in de constructor plaats, en je kunt natuurlijk ook properties gebruiken om bijv. een onder- en bovengrens van een waarde aan te geven.

Mijn voorbeeld hierboven in dit topic is niet helemaal volledig. Een Value Object is bijvoorbeeld altijd final, want je wilt dat de waarde niet kan veranderen als hij eenmaal gevalideerd is, door hem bijvoorbeeld te extenden, wat dus verboden is. Een VO heeft ook geen setters. Dat is eigenlijk de essentie van een Value Object; alleen het feit dat hij aangemaakt is en dus door de constructor-validatie komt, garandeert dat hij altijd valid is.

Er is nog veel meer te vertellen over Value Objects, maar dat valt een beetje buiten dit topic, maar er zijn goeie blogs over te vinden.

[edit]

Nog één aanvulling: wanneer je in een andere class in de constructor een type-hint naar een Value Object aangeeft, garandeer je dus dat die property altijd valid is. Bijvoorbeeld:

<?php
class Subscriber {
private $name;
private $email;

public function __construct($name, Email $email) {
$this->name = $name;
$this->email = $email;
}
}
?>

Als nu $email niet van het type Email is, of niet goed aangemaakt is, krijg je automatisch een Exception. Het scheelt je dus heel veel validatie.

[size=xsmall]Toevoeging op 29/12/2017 20:41:04:[/size]

Jan Koehoorn op 28/12/2017 20:51:17

Sowieso gebruik je nooit rechtstreeks $_POST variabelen in parameter binding.

Voordat je de waarden gebruikt om aan je insert query te koppelen, heb je alles gevalideerd (met bv. een EmailValidator class) en in orde bevonden.

Een andere optie, is werken met Value Objects, waarbij de validatie in de constructor plaatsvindt. Een Value Object voor een email adres kan er zo uitzien:


<?php
final class Email
{
    private $email;

    public function __construct($email)
    {
        if ( ! filter_var($email, FILTER_VALIDATE_EMAIL)) {
            throw new InvalidArgumentException(sprintf('[%s] is not a valid email address', $email));
        }

        $this->email = $email;
    }

    public function __toString()
    {
        return $this->email;
    }
}
?>


Het voordeel van werken met Value Objects is, dat je in je hele codebase nu nog maar één plek voor het valideren van email adressen hebt, namelijk in de constructor van dat object.


@Jan,

>> nee, de enige parameter(s) die je aan de constructor meegeeft, zijn de value(s) die je wilt gebruiken.

Oké ... maar hoe zou je dat dan doen bij een keuze met radiobuttons ... in het voorbeeldje wat ik gaf, kun je dmv een radiobutton waarde ABC123 of XYZ789 kiezen. Hoe voorkom je dan dat een hacker de waarde KLM456 verstuurt? Anders gezegd ... hoe weet dat value object dat alleen ABC123 en XYZ789 zijn toegestaan?
Voorbeeld met alleen de constructor:

<?php
class MyVerySpecificValueSet
{
private $allowed = [
'ABC123' => true,
'XYZ789' => true,
];

private $val;

public function __construct($val)
{
if (empty($this->allowed[$val])) {
throw new InvalidArgumentException(
sprintf('[%s] is not a valid value for [%s]', $val, __CLASS__)
);
}

$this->val = $val;
}
}
?>
Maar nu maak je de waardes hardcoded ... dat lijkt me niet handig, want dan kun je ze niet vanuit de formulierafhandeling meegeven. Dan zou je voor ieder formulier een aparte class moeten maken.
Het aanmaken van een class is in PHP absoluut geen dure operatie. En bovendien: hoeveel formulieren heb je op je website? Je kunt zonder enige probleem tientallen of honderden VO's aanmaken. En als je dat onoverzichtelijk vindt, dan maak je gewoon een ouderwetse Validator Class.
Ik denk dat @Ozzie doelt op bijvoorbeeld een lijst die uit je database komt. En zelf denk ik dan nog door naar een lijst met waarden die weer afhankelijk is van een andere keuze in hetzelfde formulier. In een "kassa" scherm moet je bijvoorbeeld eerst een betaalmethode kiezen (PayPal, CreditCard, iDeal, enz). Alleen in het geval van iDeal moet je vervolgens ook nog een bank kiezen. Die betaalmethode moet je valideren (stel even dat die lijst uit een database komt), en dan moet je in één specifiek geval ook nog een bank kiezen (met een lijst die meestal door een betaalprovider wordt geleverd). Dat lijkt me allemaal wat lastig in zo'n "vast" Value Object te verwerken.

(ja, ik weet, we dwalen af ...).
Het gaat er niet om of het een dure operatie is ... stel je hebt een webshop en je verkoopt duizenden producten met een simpele en een dure versie die beiden anders geprijsd zijn. Om aan te geven welke versie je wil, moet je als klant de juiste prijs selecteren. Er zijn dus maar 2 prijzen mogelijk en iedere andere bedrag is sowieso verkeerd. Je wil dan niet bij ieder product handmatig gaan aangeven welke prijzen zijn toegestaan.

(uiteraard zit hier dan ook een programmeerfout als je het op deze manier zou programmeren, maar het is puur even als voorbeeldje bedoeld)

PS

Alvorens ik dit topic nu kaap ... Ruben ... heb jij al een antwoord op je vraag?
Ja filter input met PDO in database en output filteren met htmlentities denk ik.
Ik wou er even op in gaan wat het nut van bind_param is, is dit ook en filter op je variabel?
dan zou ik er dus 2 achter elkaar hebben, niet dat het erg is.

hierna mag je het kapen.

Reageren