CodeIgniter Forums
What are you using to prevent multiple form submissions? - Printable Version

+- CodeIgniter Forums (https://forum.codeigniter.com)
+-- Forum: Archived Discussions (https://forum.codeigniter.com/forumdisplay.php?fid=20)
+--- Forum: Archived Development & Programming (https://forum.codeigniter.com/forumdisplay.php?fid=23)
+--- Thread: What are you using to prevent multiple form submissions? (/showthread.php?tid=28499)



What are you using to prevent multiple form submissions? - El Forum - 03-12-2010

[eluser]jakeone[/eluser]
I normally use a hidden token in my forms and match this to a session variable to prevent duplicate submissions.

However, it does not appear to work for me in CI.

I submit a form with deliberate errors. Errors are flagged. I fix errors and submit successfully. To test, I click "Back" and see the form with errors again. I fix errors again and submit. At this point, I expect my code to pick up the fact that it's a duplicate i.e.
Code:
$this->input->post('token') == $this->session->userdata('token')
etc. However, when I look at the page source, a new token has been generated even though I'm looking at a cached page (or I thought I was)

I can only assume that CI is running Form Validation when I click Back (e.g. the browser asks me if I want to resend the data) and this creates a new token which makes my code think it's a fresh form. Am I imagining this?

What are you guys using to prevent repeat submissions?


What are you using to prevent multiple form submissions? - El Forum - 03-12-2010

[eluser]Johan André[/eluser]
You can use this (I made a library of it, code is mainly by someone else):

Code:
<?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class Formkey
{
    private $formkey;
    private $old_formkey;
    
    function __construct()
    {
        $this->ci = & get_instance();
        $this->ci->load->library('session');
        $this->ci->load->library('form_validation');
            
        if($this->ci->session->userdata('formkey'))
        {
            $this->old_formkey = $this->ci->session->userdata('formkey');
        }
    }

    private function generate_key()
    {
        $ip = $this->ci->input->ip_address();
        $uniqid = uniqid(mt_rand(), true);
        return md5($ip . $uniqid);
    }

    
    public function render_field()
    {
        $this->formkey = $this->generate_key();
        $this->ci->session->set_userdata('formkey', $this->formkey);
        return form_hidden('formkey', $this->formkey);
    }

    public function validate()
    {
        if($this->ci->input->post('formkey') == $this->old_formkey)
        {
            return TRUE;
        }
        else
        {
            $this->ci->form_validation->set_message('_check_formkey', '%s is wrong!');
            return FALSE;
        }
    }
    
}

/* End of file */

Create a validation rule (callback__check_formkey) which calls the validate()-method of the library.


What are you using to prevent multiple form submissions? - El Forum - 03-13-2010

[eluser]jakeone[/eluser]
Thanks so much for this Johan. I managed to get it working, with a bit of tinkering. I found that by doing a "double redirect" (once when the form is first submitted successfully, and again if the user clicks "Back" and the formkey and oldkey match) it worked perfectly. Thanks for sharing.