2010-10-13 20 views
89

La página uno contiene un formulario HTML. Página dos: el código que maneja los datos enviados.Impedir el reenvío de formularios

Se envía el formulario de la página uno. El navegador se redirige a la página dos. La página dos maneja los datos enviados.

En este punto, si la página dos se actualiza, aparece una alerta "Confirmar reenvío de formulario".

¿Se puede evitar esto?

+0

Utilice un diálogo de confirmación: http://stackoverflow.com/questions/6457750/form-confirm-before-submit/12357337#12357337 –

+3

uso posterior a la redirección obtener como se describe aquí - >> http://en.wikipedia.org/wiki/Post/Redirect/Get – Meer

+0

Puede evitar eso incluso sin redirección. Mira [aquí] (https://stackoverflow.com/a/47247434/4632019) –

Respuesta

131

hay 2 se aproxima a la gente solía tomar aquí:

Método 1: uso de AJAX + redirigida

esta manera de poner un formulario en el fondo usando jQuery o algo similar a Page2, mientras que el el usuario sigue viendo la página1 mostrada. Tras publicar con éxito, redirige el navegador a la Página 2.

Método 2: post + redirigir a uno mismo

Ésta es una técnica común en los foros. El formulario en la página 1 publica los datos en la página 2, la página 2 procesa los datos y hace lo que se debe hacer, y luego realiza un redireccionamiento HTTP sobre sí mismo. De esta manera, la última "acción" que el navegador recuerda es un simple GET en la página 2, por lo que el formulario no se vuelve a enviar en F5.

+2

una variante del método 2 es una redirección a otra página. Por ejemplo, POSTES a http://example.com/save.html y una vez que se haya guardado, se redirecciona a http://example.com/list.html. – Guillaume

+1

Con el Método 1, que haría uso el plugin jQuery llamado BlockUI dejar que el cliente sabe que algo está sucediendo. – Shikiryu

+0

Estoy usando el método 2, pero me está pidiendo que vuelva a enviarlo nuevamente si lo actualizo. ¿Alguien tiene un problema similar a esto? – keen

9

Directamente, no se puede, y eso es algo bueno. La alerta del navegador está ahí por una razón. Este hilo debe responder a su pregunta:

Prevent Back button from showing POST confirmation alert

dos soluciones clave sugeridas eran el patrón PRG, y un AJAX someter seguidas de una reubicación de secuencias de comandos.

Tenga en cuenta que si su método permite un método de envío GET y no un método de envío POST, entonces eso resolvería el problema y se ajustaría mejor a la convención. Esas soluciones se proporcionan bajo la suposición de que desea/necesita enviar datos POST.

2

Si actualiza una página con datos POST, el navegador confirmará su reenvío. Si usa datos GET, el mensaje no se mostrará. También puede hacer que la segunda página, después de guardar el envío, lo redirija a una tercera página sin datos.

6

La única manera de estar 100% seguro de que el mismo formulario nunca se envía dos veces es incrustar un identificador único en cada uno que emite y rastrear los que se han enviado en el servidor. El escollo es que si el usuario realiza una copia de seguridad de la página donde estaba el formulario e ingresa nuevos datos, el mismo formulario no funcionará.

6

Hay dos partes en la respuesta:

  1. Asegurarse de mensajes duplicados no ensucia con sus datos en el lado del servidor. Para hacer esto, inserte un identificador único en la publicación para que pueda rechazar las solicitudes subsiguientes del lado del servidor. Este patrón se llama Receptor de Idempotencia en términos de mensajería.

  2. Asegúrese de que el usuario no está preocupado por la posibilidad de duplicados somete por tanto

    • volver a dirigir a un GET, tras el test (POST redirigir patrón GET)
    • deshabilitar el botón usando javascript

Nada de lo que hagas en 2. prevendrá totalmente los envíos duplicados. La gente puede hacer clic muy rápido y los hackers pueden publicar de todos modos. Siempre necesita 1. si quiere estar absolutamente seguro de que no hay duplicados.

-2

estoy usando Chrome y se puede hacer esto ...

1) se puede utilizar esta en la página que se forma sometimiento:

<?php 
    if(isset($_POST['yourpost'])){ 
     //your codes go here 
     //in the end of this lines you will do this: 
     header("Location: this same page.php"); 
     exit; 
    } 
    else{ 
     //do nothing 
    } 
?> 

su código HTML está por debajo

<html>....</html> 
+0

si vuelve a enviar el formulario, la matriz POST contendrá datos :) – daslicht

16

Es necesario utilizar PRG - Mensaje/Redirigir/Obtener patrón y que acabas de implementar la P de PRG. Necesita Redirigir. (Hoy en día no necesitas redirección en absoluto Ver this.)

PRG es un patrón de diseño desarrollo web que impide que algunos envíos de formularios duplicados que significa, Envíe el formulario (Publicar demanda 1) -> Redireccionar -> Get (Solicitud 2) código de estado

Under the hood 

redirección - HTTP 1.0 con HTTP 302 o HTTP 1.1 con HTTP 303

una respuesta HTTP con código de estado de redirección se adicionalmente proporcionar una URL en el campo de encabezado de ubicación. El agente de usuario (por ejemplo, un navegador web) es invitado por una respuesta con este código para realizar una segunda solicitud, por lo demás idéntica, a la nueva URL especificada en el campo de ubicación.

El código de estado de redireccionamiento es para garantizar que, en esta situación, el navegador del usuario de la web pueda actualizar de forma segura la respuesta del servidor sin provocar que se reenvíe la solicitud HTTP POST inicial.

Double Submit Problem 

Double Submit Problem

Post/Redirect/Get Solution 

Post/Redirect/Get Solution

Source

+2

Buena explicación. Me pregunto qué pasará si el usuario hace clic en el botón Atrás en el navegador después de que se realiza el redireccionamiento. Volverá a aparecer la ventana emergente "confirmar presentación de formulario". Supongo que incluso si la ventana emergente de confirmación no se vuelve a mostrar, se realizará una solicitud posterior en la página 1 con los mismos datos y una vez más se redirigirá al usuario a la página 2. Tengo una serie de formularios, form1, form2, form3. cómo puede volverse de la forma "n" a la forma "n-1" sin problemas. Pregunta aleatoria: ¿Dónde estudió el patrón de diseño PRG – Rpant

+0

@Rpant en Chrome? El archivo php que envía el encabezado de ubicación ni siquiera aparece en el historial del navegador, por lo que el botón Atrás simplemente lo lleva de vuelta al formulario. – FluorescentGreen5

+0

@Angelin Después de redirigir cómo obtener obtendrá los datos? Por ejemplo, cuando publico algunos datos en/some_url y me redirecciona a/some_url, que hace una solicitud GET. ¿Cómo sé cuál debería ser la respuesta ya que/some_url es genérico y no conlleva una identificación como/some_url/? –

0

El patrón PRG sólo puede prevenir la nueva presentación causada por la página refrescante. Esta no es una medida 100% segura.

Por lo general, voy a tomar acciones a continuación para evitar una nueva presentación: Lado

  1. cliente - el uso de JavaScript para evitar clics duplicados en un botón que activará el envío de formularios.Solo puede deshabilitar el botón después del primer clic.

  2. Lado del servidor: calcularé un hash en los parámetros enviados y guardaré ese hash en sesión o base de datos, de modo que cuando se reciba el envío duplicado podremos detectar la duplicación y luego la respuesta adecuada al cliente. Sin embargo, puede administrar generar un hash en el lado del cliente.

En la mayoría de las ocasiones, estas medidas pueden ayudar a prevenir el reenvío.

1

Bueno, encontré que nadie mencionó este truco.

Sin redirección, aún puede evitar la confirmación del formulario al actualizar.

Por defecto, el código de forma es la siguiente:

<form method="post" action="test.php">

ahora, cambie a <form method="post" action="test.php?nonsense=1">

Va a ver la magia.

Supongo que es porque los navegadores no activarán la ventana emergente de alerta de confirmación si obtiene un método GET (cadena de consulta) en la url.

0

Me gusta mucho la respuesta de @ Angelin. Pero si está tratando con algún código heredado donde esto no es práctico, esta técnica podría funcionar para usted.

En la parte superior del archivo

// Protect against resubmits 
if (empty($_POST)) { 
    $_POST['last_pos_sub'] = time(); 
} else { 
    if (isset($_POST['last_pos_sub'])){ 
     if ($_POST['last_pos_sub'] == $_SESSION['curr_pos_sub']) { 
      redirect back to the file so POST data is not preserved 
     } 
     $_SESSION['curr_pos_sub'] = $_POST['last_pos_sub']; 
    } 
} 

Luego, al final del formulario, palo en last_pos_sub de la siguiente manera:

<input type="hidden" name="last_pos_sub" value=<?php echo $_POST['last_pos_sub']; ?>> 
0

Try tris:

function prevent_multi_submit($excl = "validator") { 
    $string = ""; 
    foreach ($_POST as $key => $val) { 
    // this test is to exclude a single variable, f.e. a captcha value 
    if ($key != $excl) { 
     $string .= $key . $val; 
    } 
    } 
    if (isset($_SESSION['last'])) { 
    if ($_SESSION['last'] === md5($string)) { 
     return false; 
    } else { 
     $_SESSION['last'] = md5($string); 
     return true; 
    } 
    } else { 
    $_SESSION['last'] = md5($string); 
    return true; 
    } 
} 

Cómo uso/ejemplo:

if (isset($_POST)) { 
    if ($_POST['field'] != "") { // place here the form validation and other controls 
    if (prevent_multi_submit()) { // use the function before you call the database or etc 
     mysql_query("INSERT INTO table..."); // or send a mail like... 
     mail($mailto, $sub, $body); // etc 
    } else { 
     echo "The form is already processed"; 
    } 
    } else { 
    // your error about invalid fields 
    } 
} 

Fuente: https://www.tutdepot.com/prevent-multiple-form-submission/

Cuestiones relacionadas