2009-05-20 11 views
20

Un problema web común es cuando un usuario hace clic varias veces en el botón de enviar de un formulario para que el servidor procese el formulario más de una vez. Esto también puede suceder cuando un usuario presiona el botón Atrás y luego envía un formulario para que se procese de nuevo.¿Qué métodos están disponibles para detener varias devoluciones de un formulario en ASP.NET MVC?

¿Cuál es la mejor manera de evitar que esto ocurra en ASP.NET MVC?

posibilidades como lo veo son:

  1. deshabilitar el botón después de someter - ahora se pone alrededor de los múltiples clics, pero no la navegación
  2. Tener la acción de recepción redirigir inmediatamente - navegadores parecen dejar estas redirecciones a cabo de la historia
  3. colocar una ficha única en la sesión y en la forma - si coinciden procesar la forma - si no borrar el formulario para presentar una nueva

¿Hay más?

¿Existen algunas implementaciones específicas de alguno de estos?

Puedo ver la tercera opción implementada como un ActionFilter con una extensión HtmlHelper de una manera similar a las cosas anti-falsificación.

Esperamos con interés escuchar de usted MVC'ers por ahí.

Respuesta

16

A menudo las personas pasan por alto la forma más convencional de manejar esto, que es el uso de las teclas nonce.

Puede utilizar PRG como otros han mencionado, pero el inconveniente es que con el PRG no resuelve el problema del doble clic, se requiere un viaje adicional al servidor para la redirección, y puesto que el último paso es una solicitud GET no tiene acceso directo a los datos que acabamos de publicar (aunque podría pasarse como un parámetro de consulta o mantenerse en el servidor).

Me gusta la solución de Javascript porque funciona más del tiempo.

Nonce keys Sin embargo, funcionan todo el tiempo. La clave nonce es un GUID único y aleatorio generado por el servidor (también guardado en la base de datos) e incrustado en el formulario. Cuando el usuario PUBLICA el formulario, la clave nonce también se publica. Tan pronto como entra un POST al servidor, el servidor verifica que la clave nonce exista en su base de datos. Si lo hace, el servidor borra la clave de la base de datos y procesa el formulario. En consecuencia, si el usuario realiza una POST dos veces, la segunda POST no se procesará porque la clave nonce se eliminó después de procesar la primera POST.

La clave nonce tiene una ventaja adicional ya que brinda seguridad adicional al evitar replay attacks (un hombre en el medio olfatea su solicitud HTTP y luego la reproduce en el servidor que la trata como legítima).

+0

Una idea interesante, una cosa que agregaría es que debe poner la secuencia en una transacción: 1) verificar nonce 2) proceso 3) eliminar nonce. Si no lo haces atómicamente, tienes una condición de carrera en la que la publicación se puede procesar varias veces, especialmente. si el procesamiento tarda un tiempo en finalizar (y el usuario está impaciente). Una cosa de la que todavía no tengo claro es que si el POST detecta un envío duplicado, ¿qué debería devolverse al usuario? ¿Una página que indica que la publicación está en progreso? – DSO

+0

Yo eliminaría primero la clave nonce y luego haré el procesamiento para mantener las cosas simples. Cómo manejar un engaño es una decisión de diseño y depende de usted. Sin embargo, una respuesta descriptiva de lo que acaba de suceder ayudaría al usuario a apreciar aún más su aplicación web. – aleemb

+0

¿Has visto una implementación de claves nonce en ASP.NET MVC usando ActionFilters quizás? Me imagino que esto haría que la implementación sea muy simple y reutilizable. También podría usar una base de datos o simplemente una variable de sesión. – WooWaaBob

1

Esto realmente no es específico de MVC, pero el patrón que seguimos en nuestras páginas web es que las acciones se realizan con llamadas AJAX, en lugar de publicaciones POST de página completa. Así que navegar a una URL nunca realiza una acción, solo muestra el formulario. La llamada AJAX no estará en el historial

0

Junto con la desactivación de botones, puede agregar un div transparente a toda la página web para que el clic no genere nada. Hacemos esto en mi trabajo y agrego una pequeña etiqueta amigable que dice solicitud de procesamiento.

5

Siempre debe devolver una redirección como respuesta HTTP a una POST. Esto evitará que la POST vuelva a ocurrir cuando el usuario navega hacia adelante y hacia atrás con los botones Adelante/Atrás en el navegador.

Si le preocupa que los usuarios hagan doble clic en sus botones de envío, solo tiene un pequeño script para deshabilitarlos inmediatamente al enviarlos.

+0

¿qué pasa con nuestros preciosos no js usuarios? – redsquare

+0

Las secuencias de comandos pueden ser no intrusivas e insertarse de forma que no molesten a navegadores/usuarios que no sean js. Si todavía te preocupan los envíos de forma dual, necesitas una lógica del lado del servidor para manejar eso. – mookid8000

+0

eso es a lo que me refería. La lógica está mejor implementada en el lado del servidor que confiar en js – redsquare

2

Es posible que desee observar el patrón Post-Redirect-Get (PRG):

+1

El patrón PRG no resuelve el problema de que el usuario haga clic en enviar varias veces. – DSO

+0

No, no soluciona el problema del botón Atrás aunque –

+0

puede evitar fácilmente el doble clic con una función javascript simple. – josephdotca

Cuestiones relacionadas