proyectos ejemplos database perl cgi idempotent

database - ejemplos - django



¿Cómo puedo evitar que la base de datos se vuelva a escribir cuando el navegador realiza una recarga/retroceso? (7)

Estoy armando una pequeña aplicación web que escribe en una base de datos (Perl CGI y MySQL). El script CGI toma información de un formulario y lo escribe en una base de datos. Noté, sin embargo, que si presiono ''Volver a cargar'' o ''Atrás'' en el navegador web, volverá a escribir los datos en la base de datos. No quiero esto

¿Cuál es la mejor manera de protegerse contra los datos que se vuelven a escribir en este caso?


El uso de una solicitud POST hará que el navegador intente evitar que el usuario vuelva a enviar la misma solicitud, pero yo recomendaría utilizar algún tipo de seguimiento de transacciones basado en sesiones para que el usuario ignore las advertencias del navegador y vuelva a enviar su consulta su aplicación evitará la duplicación de cambios en la base de datos. Puede incluir una entrada oculta en el formulario de envío con el valor establecido en un hash de cifrado y registrar ese hash si la solicitud se envía y procesa sin error.


Me resulta útil para rastrear la cantidad de presentaciones de formularios que el usuario ha realizado en su sesión. Luego, al renderizar el formulario, creo un campo oculto que contiene ese número. Si el usuario vuelve a enviar el formulario presionando el botón Atrás, enviará el viejo # y el servidor puede decir que el usuario ya ha enviado el formulario al examinar lo que está en la sesión a lo que está diciendo el formulario.

Solo mis 2 centavos.


Si aún no está utilizando algún tipo de gestión de sesión (que le permitiría observar y rastrear envíos de formularios), una solución simple sería incluir algún tipo de identificador único en la forma (como un elemento oculto) que sea una parte de la transacción DB principal en sí, o rastreado en una tabla DB separada. Luego, cuando se envía un formulario, verifica la identificación única para ver si ya se ha procesado. Y cada vez que se genera el formulario, solo tiene que asegurarse de tener una ID única.


¡No use las solicitudes GET para hacer modificaciones! Sé RESTful ; use POST (o PUT) en su lugar, el navegador debe advertir al usuario que no vuelva a cargar la solicitud. El redireccionamiento ( usando la redirección de HTTP ) a una página de recibo utilizando una solicitud GET normal después de una solicitud POST / PUT hará posible actualizar la página sin que se lo advierta sobre volver a enviar.

EDITAR:

Supongo que el usuario ha iniciado sesión de alguna manera y, por lo tanto, ya tiene alguna forma de rastrear al usuario, por ejemplo, sesión o similar.

Puede hacer una marca de tiempo (o un hash aleatorio, etc.) al mostrar el formulario que lo almacena como un campo oculto ( justo al lado del token anti de Solicitud entre sitios que estoy seguro que ya tiene ), y en una variable de sesión (que se almacena de forma segura en su servidor), cuando recibe una solicitud POST / PUT para este formulario, comprueba que la marca de tiempo sea la misma que la sesión. Si es así, estableces la marca de tiempo en la sesión en algo variable y difícil de adivinar (la marca de tiempo concatenada con alguna cadena secreta, por ejemplo) luego puedes guardar los datos del formulario. Si alguien repite la solicitud ahora, no encontrará el mismo valor en la variable de sesión y rechazará la solicitud.

El problema al hacer esto es que el formulario no es válido si el usuario hace clic atrás para cambiar algo, y puede ser un poco duro, a menos que sea dinero el que está actualizando. Por lo tanto, si tiene problemas con usuarios "estúpidos" que actualizan y hacen clic en el botón "Atrás" accidentalmente reenviando algo, simplemente usar POST les recuerda que no hagan eso, y redirigir lo hará menos probable. Si tiene un problema con usuarios malintencionados, también debe usar un intervalo de tiempo, aunque a veces puede confundir a los usuarios, aunque si los usuarios publican deliberadamente el mismo mensaje una y otra vez, es probable que deba encontrar una forma de prohibirlos. Usar POST, tener un timestam e incluso hacer una comparación completa de toda la base de datos para buscar publicaciones duplicadas, no servirá de nada si los usuarios maliciosos simplemente escriben un script para cargar el formulario y enviar basura al azar automáticamente. (Pero la protección de solicitud entre sitios hace que sea mucho más difícil)


En primer lugar, no puede confiar en el navegador, por lo que cualquier conversación sobre el uso de POST en lugar de GET es principalmente nerd flim-flam. Sí, el cliente podría recibir una advertencia del tipo "¿Quería volver a enviar esta información nuevamente?", Pero es muy probable que diga "Sí, ahora déjeme solo, estúpida computadora".

Y con razón: si no quieres envíos duplicados, entonces es tu problema resolverlo, no el del usuario.

Es de suponer que tienes una idea de lo que significa ser una presentación duplicada. Tal vez sea la misma dirección IP en unos segundos, tal vez sea el mismo título de una publicación de blog o una URL que se haya enviado recientemente. Tal vez se trate de una combinación de valores, por ejemplo, dirección IP, dirección de correo electrónico y el encabezado de un envío de formulario de contacto. De cualquier forma, si ha detectado manualmente algunos duplicados en sus datos, debería poder encontrar una forma de identificar mediante programación un duplicado en el momento de la presentación, y marcarlo para su aprobación manual (si no está seguro), o simplemente le dice al remitente "¿Ha hecho doble clic?" (Si la información no es sorprendentemente confidencial, podría presentar el registro existente que tiene para ellos y decir "¿Es esto lo que usted quiso enviarnos? Si es así, ya lo ha hecho - ¡hurra!")


No confiaría en las advertencias POST del navegador. Los usuarios simplemente hacen clic en Aceptar para que los mensajes desaparezcan.

Cada vez que tenga una solicitud que debe ser única, por ejemplo, "realizar un pago", envíe un token único, que se reenviará con la solicitud. Tire el token después de que vuelva, y así podrá saber cuándo algo es un envío válido (cualquier cosa con un token que no esté ''activo''). Expirar tokens activos después de X cantidad de tiempo, por ejemplo, cuando finaliza una sesión de usuario.

(alternativamente rastrear los tokens que han regresado, y si lo ha recibido antes, entonces no es válido).


Haga un POST cada vez que modifique datos, pero nunca devuelva una respuesta HTML de una publicación ... en su lugar devuelva un redireccionamiento a un GET que recupera los datos actualizados como una página de confirmación. De esta forma, no hay que preocuparse de que actualicen la página. Si se actualizan, todo lo que sucederá es otra recuperación, nunca una acción que altere los datos.