Alweer een vraag? Ja, helaas of gelukkig wel. Kan ik jullie kennis wederom aanspreken.

Ik heb een formulier, dat roept een php aan. Werkt goed. Maar nu wil ik vermijden dat een gebruiker deze laatste pagina refreshed, F5 of Ctrl F5. Ik heb gelezen dat je met unset $_POST iets kunt doen. Nou dat werkt niet.

Ik check if($_SERVER['REQUEST_METHOD']=="POST") {

Wat is jullie ervaring om dit op te lossen? Want elke refresh voegt de gegevens toe aan de database. Dus vervelend. Is dat op de lossen?
Je zou naar een beveiliging kunnen kijken met CSRF, waarbij je steeds een nieuwe hash genereert in je sessie, en deze controleert in een hidden POST value.
Wat veel wordt toegepast is Post/Redirect/Get. Kortom, na het posten en valideren van gegevens redirect je naar een nieuwe pagina, desnoods met een flash message in je session ter bevestiging. Dat voorkomt dat je na refreshes meer gegevens in je database krijgt.
Flash message?
Dank. CSRF klinkt lijkt niet eenvoudig. Ik bedacht wat anders:

Zou ik ook een $_SESSION['nieuw'] kunnen gebruiken? In de pagina waar ik de php aanroep, $_SESSION['nieuw']= true zetten vervolgens na de eerste check in de POST PHP deze $_SESSION['nieuw']=false zetten. Dan voorin checken of if ($_SESSION['nieuw']) melding en terug naar formulier of ander pagina. Kan dat?
Die sessie wordt dan na een rehresh zo weer opnieuw aangemaakt. En CSRF is nog best kinderlijk eenvoudig te bouwen. Deze gebruik ik in mijn CMS, en heeft Dylan volgens mij eens gebouwd.


<?php
class Csrf {

    public static function makeToken() {
        $max_time    = 60 * 60 * 24;
        $csrf_token  = $_SESSION['csrf_token'];
        $stored_time = $_SESSION['csrf_token_time'];

        if ( $max_time + $stored_time <= time() || empty( $csrf_token ) ) {
            $_SESSION['csrf_token'] = md5( uniqid( rand(), true ) );
            $_SESSION['csrf_token_time'] = time();
        }

        return $_SESSION['csrf_token'];
    }

    public static function isTokenValid( $field ) {
        return $field === $_SESSION['csrf_token'];
    }
}
?>



 <input type="hidden" name="csrf_token" value="<?= Csrf::makeToken(); ?>"> 



 <?php
if( Csrf::isTokenValid( $_POST['csrf_token'] ) ) {
    echo 'Valid';
} else {
    echo 'Nope';
} 
?>


Wat ik een hash noemde, heet hier een token.
hoezo niet eenvoudig?


<form action="/foo.php" method="post">

</form>


en in php staat:

<?php 
 if('POST' == $_SERVER['REQUEST_METHOD']) {
     // doe je ding. Bijvoorbeeld een insert

     // zorg dat er niets naar het scherm gestuurd wordt. (nog geen spatie, echt niets)
     header('Location: /foo.php', true, 303);
     exit();
  }
?>
  <p>zijn we weer, maar nu met 'get'</p>


[size=xsmall]Toevoeging op 19/03/2018 12:12:12:[/size]

en als je dan op F5 drukt, wordt de laatste (GET) request herhaald en kom je dus gewoon steeds op "zijn we weer" uit.
maar als je twee keer op back drukt? Of is het POST-proces al uit de browser verwijderd?

Eigenlijk is CSRF er meer voor bedoeld dat je niet een actie kan uitvoeren via een aanval, van bijv. een externe site.
Als je op back drukt is de post niet beschikbaar, omdat je vanuit de POST een redirect hebt gedaan. De pagina bestaat voor de historie niet.
Oef... hier moet ik eens dieper induiken. Kennelijk toch niet zo gemakkelijk.
Het ligt eraan tegen wat je je wilt beschermen. Als het enkel refreshen is is POST-Redirect-Get al voldoende.
Als je niet wilt iemand bijv. URL's op je site aanroept via scriptjes, dan is CSRF de way to go.

Reageren