Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Hi Monks!

I have a program that get inputs from a form to insert data into two database tables, the problem is when I am done with the inserts the last thing that this sub routine does is to call another sub routine to display the results to the user so they can print them. My problem is if they refresh the browser I am getting the whole thing inserted into the database again. What would be the best way to prevent such thing to happen?
I was thing about setting up a cookie at the begging of my code and read the cookie at the beginning of my insert sub routine, and if the cookies exist redirect them, any thoughts?

sub insert { my %cookies = fetch CGI::Cookie; # retrieve the user_id cookie my $section = $cookies{"id"}; if($section){ # If the cookies has been set send them back somewhere. &display; } get all the values from form ....... do the inserts done with insert... #call display sub to user &display; } # end sub insert

Replies are listed 'Best First'.
Re: Preventing Duplicates
by bart (Canon) on Mar 26, 2008 at 13:07 UTC
    You're not the only one having this problem: even Perlmonks suffers from it.

    Basically I see 2 main approaches to prevent it:

    1. Add some form id to your form, which can be used only once. It may be just a counter value, or a random number, but you must make sure it's never used again. If your system notices a repost, thus, a form id that is used more than once in a submit, it should either reject the data, or update the data that got inserted before.
    2. Do not show your results in the same page that received and processed the data. In other words: redirect. The page that recieves the data then inserts it, and next jumps to another URL which only shows the data, and which is safe to reload. The main problem I see here is passing the status messages to the next page. Preferably, IMO, they should disappear after a reload.

    Oracle appears to use yet another mechanism in their Web-PL/SQL system (as generated by Oracle Designer), in particular for updates: they add the previous values for record fields as hidden form variables, and check if these values are still the current values at the moment of the update. If not, it'll complain and refuse to do the update. That way, you cannot overwrite other people's changes by accident. Not a bad idea, IMO. (What I do find a bit odd is the name they give to this mechanism: "record locking".)

      they add the previous values for record fields as hidden form variables, and check if these values are still the current values at the moment of the update.
      Unless combined with both encryption and digital signatures, I'd say it would generally be a security risk to pass data to the browser and rely on that they come back unaltered.

      Don't hide sensitive information in hidden form fields, (searchsecurity.techtarget.com).

      Update: Re-phrased "it is" to "it would generally be".

      --
      Andreas
        You may alter them all you like, after all, those are the values that you are allowed to edit. But, unless the hidden values are identical with the current values for those fields in the database, the update will not happen.

        That means that, for the update to take place, that either you have to not touch the hidden values at all, or, if the record got updated in the meantime, you must know exactly what you're doing, and manually fill in the new exact current value for those fields.

        I agree that it's a bit of an overkill, especially for long strings, to send the same data to the browser more than once. After all, just sending a CRC or digest value (MD5, SHA1,...) would suffice, for the check.

Re: Preventing Duplicates
by derby (Abbot) on Mar 26, 2008 at 12:34 UTC

    You could go the cookie route, or instead of displaying the results to the user so they can print, you could just redirect. The script you redirect to could then display the results to be printed (and refreshes at this point just redisplay the results). This is one of the things I love about CGI::Application and it's ability to have simple four line scripts that can put you at the right place in your application.

    -derby
Re: Preventing Duplicates
by andreas1234567 (Vicar) on Mar 26, 2008 at 12:35 UTC
    What would be the best way to prevent such thing to happen?
    A unique key?
    --
    Andreas