Pregunta

¿Cuál es la mejor manera de evitar que un formulario se vuelva a procesar cuando un usuario presiona el botón Atrás?

Estoy siguiendo el Publicar / Redirigir / Obtener patrón , entonces No tengo ningún problema si se presiona F5, pero el botón de retroceso aún ofrece la oportunidad de volver a enviar el formulario. Si este formulario es una página de procesamiento de tarjeta de crédito, es malo.

Esta pregunta se ha hecho algo aquí , pero la redacción y las respuestas fueron de baja calidad y no específicas de este problema exactamente.

Tengo form.php que se envía a sí mismo. Si no hubo errores en los datos de entrada al enviarlos, el usuario es redirigido a form_thanks.php. Volver a enviar (y "Enviar" o "Volver a enviar") una vez que vuelve a enviar form.php (¡MALO!) Y luego los devuelve a form_thanks.php.

Incluya también soluciones que no impliquen el uso de Sesiones, si es posible.

¿Fue útil?

Solución 2

Esto debe hacerse con un token de un solo uso, o un nonce . El servidor php / debe incluir este token en un campo de formulario oculto.

Debe almacenar una lista de todos los tokens recientes y cada vez que se envía un formulario, debe verificar si el token está en la lista de tokens válidos recientes.

Si no está en la lista, no vuelva a procesar el formulario.
Si está en la lista, procese el formulario y elimine el token de la lista.

Los tokens se pueden manejar dentro de las sesiones o simplemente una tabla de base de datos simple sin sesiones. Sin embargo, los tokens deben ser específicos del usuario.

Esta es también la forma recomendada de evitar ataques CSRF .

Otros consejos

Lo haría de una manera diferente. Coloque una entrada oculta con una cadena aleatoria como valor, y cuando se envíe guarde esa cadena aleatoria en una sesión. Configure una verificación simple para ver si ya la han publicado y si no han aceptado la entrada.

Solo estoy pensando en voz alta aquí. Pero, ¿qué pasa con una variación en post / redirect / get donde el get final no es en realidad el get final;) ??sino que, a su vez, siempre se reenvía automáticamente a la página realmente final, por lo que si el usuario presiona el botón Atrás, regresa ¿De dónde vinieron?

EDITAR:

Ok, teniendo en cuenta el comentario del OP, aquí hay otra idea. Se podría hacer que la URL para el envío del formulario requiera un parámetro que sea bueno para un solo uso. Ese token se generaría (usando MD5 o algo así) antes de enviar el formulario y podría almacenarse en una base de datos (en respuesta a la sugerencia de otra persona de que solicitó una solución sin usar sesiones). Después de procesar el formulario, este token se marcaría en la base de datos como si ya se hubiera utilizado. De modo que cuando se vuelve a la página con el mismo token, se pueden tomar medidas para evitar el reenvío de los datos del formulario al backend.

Respuesta tardía, pero uno podría evitar el procesamiento por completo utilizando una solución basada en AJAX; no habría problema en incluir un nonce con este esquema de procesamiento, pero al usar una consulta asincrónica que, en caso de éxito, redirige al usuario, las solicitudes no se repiten al actualizar, presionar hacia atrás o cualquier otra cosa que no sea hacer clic en el botón.

También es fácil implementar un mecanismo que evite que el botón se presione dos veces o se bloquee " si algo sucedió durante la solicitud al incrustar en el controlador de la solicitud (ya sea de alto nivel con PrototypeJS o jQuery o de bajo nivel con su función handrolled) los mecanismos para habilitar y deshabilitar el botón cuando la solicitud se complete y se active por primera vez, respectivamente.

Creo que la parte posterior traerá el formulario al estado que tenía antes de que la página fuera redirigida, si ese es el caso, tenga una entrada / variable oculta o algo que comience con un valor que diga verdadero, luego, una vez que se envíe el formulario, y si el valor es verdadero, cámbielo a falso y luego envíelo; de lo contrario, devuelva falso

Prueba esto:

<SCRIPT type="text/javascript">
    window.history.forward();
</SCRIPT>
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top