2010-07-08 24 views
61

El problemaBuenas Prácticas para pasar datos entre páginas

En la pila que nos re-uso entre los proyectos, que están poniendo un poco demasiados datos en la sesión para pasar datos entre las páginas. Esto fue bueno en teoría porque evita la manipulación, los ataques de reproducción, etc., pero crea tantos problemas como resuelve.

La pérdida de sesión en sí es un problema, aunque es en su mayoría manejado mediante la implementación de Servidor de estado de sesión (o mediante el uso de SQL Server). Más importante aún, es complicado hacer que el botón Atrás funcione correctamente, y también es un trabajo extra crear una situación en la que un usuario pueda, por ejemplo, abrir la misma pantalla en tres pestañas para trabajar en diferentes registros.

Y eso es solo la punta del iceberg.

Existen soluciones para la mayoría de estos problemas, pero a medida que avanzo, toda esta fricción me da la sensación de que pasar los datos entre las páginas que usan la sesión es la dirección incorrecta.

Lo que realmente quiero hacer aquí es crear una práctica recomendada que mi tienda pueda usar todo el tiempo para pasar datos entre páginas, y luego, para nuevas aplicaciones, reemplazar las partes clave de nuestra pila que actualmente dependen de Session. .

También estaría bien si la solución final no da como resultado montañas de código de plomería.

soluciones propuestas

Sesión

Como se mencionó anteriormente, apoyándose en Sesión parece como una buena idea, pero se rompe el botón atrás y hace que algunos otros problemas.

Puede haber formas de evitar todos los problemas, pero parece mucho trabajo extra.

Una cosa que es muy agradable sobre el uso de la sesión es el hecho de que la manipulación no es un problema. En comparación con pasar todo a través de QueryString no encriptado, terminas escribiendo mucho menos código de protección.

cruzada página de publicación

En verdad apenas he considerado esta opción. Tengo un problema con qué tan estrechamente acoplado hace las páginas, si empiezo a hacer PreviousPage.FindControl ("SomeTextBox"), eso parece un problema de mantenimiento si alguna vez quiero acceder a esta página desde otra página que quizás no tenga un control llamado SomeTextBox.

Parece limitado en otras formas también. Tal vez quiero llegar a la página a través de un enlace, por ejemplo.

cadena de consulta

Actualmente estoy inclinando hacia esta estrategia, al igual que en los viejos tiempos. Pero probablemente quiera encriptar mi QueryString para que sea más difícil de manipular, y me gustaría manejar el problema de los ataques de repetición también.

En 4 tipos de Rolla, there's an article about this.

Sin embargo, debería ser posible crear un HttpModule que se encargue de todo esto y elimine toda la encriptación de salchichas de la página. Efectivamente, Mads Kristensen has an article where he released one. Sin embargo, los comentarios lo hacen parecer que tiene problemas con escenarios extremadamente comunes.

Otras opciones

Por supuesto, esto no es una mirada a las opciones exaustive, sino más bien las principales opciones que estoy considerando. This link contiene una lista más completa. Los que no mencioné, como Cookies y Caché, no son apropiados para pasar datos entre páginas.

En el cierre ...

Entonces, ¿cómo está manejando el problema de pasar datos entre las páginas? ¿Qué trampas ocultas tenía que solucionar, y existen herramientas preexistentes que solucionen todo sin problemas? Do ¿Sientes que tienes una solución con la que estás completamente satisfecho?

¡Gracias de antemano!

Actualización: Sólo en caso de que no estoy siendo lo suficientemente claro, por 'pasar datos entre páginas' Estoy hablando, por ejemplo, pasando una clave IdCliente desde una página CustomerSearch.aspx a Customers.aspx, donde se abrirá el cliente y podrá editarse.

Respuesta

7

Varios meses después, pensé que actualizaría esta pregunta con la técnica con la que terminé, ya que funcionó muy bien.

Después de jugar con un manejo de estado de sesión más complicado (lo que dio como resultado una gran cantidad de botones rotos, etc.) terminé rodando mi propio código para manejar las QueryStrings cifradas. Ha sido una gran victoria: todos los escenarios de mis problemas (botón Atrás, varias pestañas abiertas al mismo tiempo, estado de sesión perdida, etc.) se resuelven y la complejidad es mínima ya que el uso es muy familiar.

Esto todavía no es una bala mágica para todo, pero creo que es bueno para el 90% de los escenarios que se encuentran.

detalles

que construyeron una clase llamada CorePage que hereda de página. Tiene métodos llamados SecureRequest y SecureRedirect.

Por lo que se podría llamar:

SecureRedirect(String.Format("Orders.aspx?ClientID={0}&OrderID={1}, ClientID, OrderID) 

CorePage analiza la cadena de consulta y cifra en una variable de cadena de consulta denominado CoreSecure. Por lo que la solicitud real se parece a esto:?

Orders.aspx CoreSecure = 1IHXaPzUCYrdmWPkkkuThEes% 2fIs4l6grKaznFGAeDDI% 3d

Si está disponible, el ID de usuario conectado en ese momento se añade a la clave de cifrado, por lo ataques de reproducción no son tan gran parte de un problema.

A partir de ahí, puede llamar a:

X = SecureRequest("ClientID") 

Conclusión

Todo funciona sin problemas, utilizando la sintaxis familiar.

En los últimos meses también he adaptado este código para trabajar con casos extremos, como hipervínculos que desencadenan una descarga; a veces es necesario generar un hipervínculo en el cliente que tenga una QueryString segura. Eso funciona realmente bien.

Avíseme si desea ver este código y lo subiré a algún lado.

Una última reflexión: es extraño aceptar mi propia respuesta sobre algunos de los mensajes muy reflexivos que otras personas hacen aquí, pero esta realmente parece ser la respuesta definitiva a mi problema. Gracias a todos los que me ayudaron a llegar allí.

+1

Del mismo modo que el cifrado de comentarios en sí mismo no resuelve realmente el aspecto de seguridad de pasar identificadores en QueryString, simplemente hace que sea mucho más difícil de moderar con ellos. En una aplicación segura, usted tiende a tener algún tipo de identidad en sesión, digamos el nombre de usuario. Entonces, si tiene una página Orders.aspx? OrderId = 1, en sus capas inferiores (servicio/negocio) siempre puede poner en la lógica de validación para asegurarse de que la orden recuperada por esta identificación en realidad pertenece al usuario que está conectado a la aplicación. – e36M3

+0

@ e36M3: Buen punto. Esta herramienta no indica cómo se almacena su ID de usuario, es solo una capa sobre Solicitud y redireccionamiento. Por lo tanto, ciertamente podría usarse de esa manera, solo necesitaría almacenar su ID de usuario en sesión y escribir el código de validación. Definitivamente estoy haciendo la parte de validación ahora, aunque debo admitir que estoy almacenando el ID de usuario en una cookie cifrada que no es perfecta. Pero quiero intentar no confiar en la sesión en absoluto. Y estos no son proyectos de alto perfil. Siempre hay margen de mejora .. –

+2

por favor ¿puedes publicarlo en github? Puedes resolver el problema de otra persona ... – CodeArtist

3

Nunca haría esto. Nunca tuve problemas para almacenar todos los datos de la sesión en la base de datos y cargarlos en función de la cookie de los usuarios. Es una sesión en lo que a nada concierne, pero mantengo el control sobre ella. No pierda el control de los datos de su sesión en su servidor web ...

Con un poco de trabajo, puede admitir sesiones secundarias y permitir tareas múltiples en diferentes pestañas/ventanas.

+0

Así que, para que quede claro, * ¿estás * usando la sesión para pasar datos entre páginas? Entonces, por ejemplo, si tiene una aplicación crud con una página de Clientes, puede establecer la sesión ("CustomerID") = 5 y luego hacer Response.Redirect ("Customers.aspx")? –

+0

No. Estoy usando una cookie, para hacer coincidir con la base de datos, para cargar los datos relacionados.No uso la funcionalidad de sesión proporcionada de ASP o .NET o PHP, etc. Utilizo una clase (llamada Session, hah) y el constructor intentará hacer coincidir la cookie de los usuarios con una sesión existente, o crear una nueva. . Los datos se pueden vincular a partir de ahí ... – Fosco

+0

Ok, eso es interesante, puedo ver cómo se puede construir una gran cantidad de bondad adicional de esa manera. Sin embargo, en última instancia, utiliza su objeto de sesión homebrew para realizar los pasos básicos mencionados anteriormente, ¿no? –

2

Como punto de partida, me parece que utilizar los elementos de datos críticos, como un ID de cliente, es mejor ponerlos en la cadena de consulta para su procesamiento. Puede rastrear/filtrar fácilmente los datos incorrectos procedentes de estos elementos, y también permite cierta integración con el correo electrónico u otros sitios/aplicaciones relacionados.

En una aplicación anterior, la única forma de ver un empleado o un registro de solicitud que los involucraba era iniciar sesión en la aplicación, buscar al empleado o buscar registros recientes para encontrar el registro en cuestión. Esto se volvió problemático y un gran inconveniente cuando alguien de un departamento relacionado necesitó hacer una simple vista en los registros para fines de auditoría.

En la reescritura, hice tanto el Id del empleado, y solicité los Id disponibles a través de una URL básica de "ViewEmployee.aspx? Id = XXX" y "ViewRequest.aspx? Id = XXX". La aplicación se configuró para A) filtrar Ids incorrectos y B) autenticar y autorizar al usuario antes de permitirle acceder a estas páginas. Lo que esto permitió que los usuarios de la aplicación primaria hicieran era enviar correos electrónicos simples a los auditores con una URL en el correo electrónico. Cuando tenían mucha prisa, estaban en su tiempo de procesamiento masivo, podían simplemente hacer clic en una lista de URL y realizar el procesamiento adecuado.

Otros datos relacionados con la sesión, como las fechas de modificación y el mantenimiento del "estado" de la interacción del usuario con la aplicación se vuelven un poco más complejos, pero espero que esto proporcione un punto de partida para usted.

41

En primer lugar, los problemas con los que se relaciona se relacionan con el estado de manejo en un entorno sin estado.Las dificultades que está teniendo no son nuevas y es probablemente una de las cosas que hace que el desarrollo web sea más difícil que el desarrollo de Windows o el desarrollo de un ejecutable.

Con respecto al desarrollo web, tiene cinco opciones, hasta donde tengo conocimiento, para manejar el estado específico del usuario que se puede usar en combinación entre sí. Descubrirá que ninguna solución funciona para todo. En su lugar, es necesario determinar cuándo utilizar cada solución: cadena

  • consultas - Las cadenas de consulta son buenas para pasar punteros a los datos (por ejemplo, valores de clave primaria) o valores de estado. No se debe asumir que las cadenas de consulta por sí mismas son seguras, incluso si están encriptadas debido a la repetición. Además, algunos navegadores tienen un límite en la longitud de la url. Sin embargo, las cadenas de consulta tienen algunas ventajas, como que pueden marcarse y enviarse por correo electrónico a las personas y son inherentemente apátridas si no se utilizan con otra cosa.

  • Cookies - Las cookies son buenas para almacenar cantidades muy pequeñas de información para un usuario en particular. El problema es que las cookies también tienen una limitación de tamaño, después de lo cual simplemente truncarán los datos, por lo que debe tener cuidado al colocar datos personalizados en una cookie. Además, los usuarios pueden matar las cookies o detener su uso (aunque eso también impediría el uso de la sesión estándar). Al igual que en las cadenas de consulta, las cookies son mejores, IMO, para los punteros a los datos que para los datos en sí, a menos que los datos sean pequeños.

  • Datos de formulario: los datos de formulario pueden llevar bastante información, pero a costa de los tiempos de publicación y, en algunos casos, de los tiempos de recarga. ViewState de ASP.NET utiliza variables ocultas de formulario para mantener la información. Pasar datos entre páginas usando algo como ViewState tiene la ventaja de trabajar mejor con el botón Atrás, pero puede crear fácilmente páginas descomunales que ralentizan la experiencia para el usuario. En general, el modelo de ASP.NET no funciona en la publicación de páginas cruzadas (aunque es posible), sino que funciona en las publicaciones de vuelta a la misma página y desde allí navega a la página siguiente.

  • Sesión: la sesión es útil para obtener información relacionada con un proceso con el que el usuario está progresando o para una configuración general. Puede almacenar bastante información en sesión a costa de la memoria del servidor o los tiempos de carga de las bases de datos. Conceptualmente, la sesión funciona cargando todo el fajo de datos para el usuario, todo de una vez desde la memoria o desde un servidor de estado. Eso significa que si tiene un conjunto de datos muy grande probablemente no quiera ponerlo en sesión. La sesión puede crear algunos problemas de botón de retroceso que deben sopesarse con respecto a lo que el usuario realmente intenta lograr. En general, encontrará que el botón Atrás puede ser la perdición del desarrollador web.

  • Base de datos - La última solución (que nuevamente se puede usar en combinación con otras) es que almacena la información en la base de datos en su esquema apropiado con una columna que indica el estado del elemento. Por ejemplo, si maneja la creación de un pedido, puede almacenar el pedido en la tabla de pedidos con una columna de "estado" que determine si se trata de un pedido real o no. Debería guardar el identificador de orden en la cadena o sesión de consulta. El sitio web continuará escribiendo datos en la tabla para actualizar las diversas partes y elementos secundarios hasta que, finalmente, el usuario pueda declarar que están hechos y que el estado de la orden esté marcado como un pedido real. Esto puede complicar los informes y consultas en el sentido de que todos necesitan diferenciar los elementos "reales" de los que están en proceso.

Uno de los elementos mencionados en su último enlace fue Caché de la aplicación. No consideraría que esto sea específico del usuario, ya que es una aplicación amplia. (Obviamente, puede ser con una horma para ser específico del usuario, pero tampoco lo recomendaría). Nunca he jugado con el almacenamiento de datos en el HttpContext fuera de pasarlo a un controlador o módulo, pero sería escéptico que fuera diferente de las soluciones mencionadas.

En general, no existe una única solución que los gobierne a todos. El mejor enfoque es asumir en cada página que el usuario podría haber navegado a esa página desde cualquier lugar (en lugar de asumir que llegaron allí mediante el uso de un enlace en otra página). Si lo haces, los problemas del botón de retroceso se vuelven más fáciles de manejar (aunque sigue siendo un problema). En mi desarrollo, utilizo los primeros cuatro ampliamente y en ocasiones recurro a la última solución cuando la necesita.

+0

Hola Thomas, gracias por la respuesta. Acepté la respuesta de sw12345 porque no buscaba tanto los pros y los contras de las diversas opciones como algunas ideas avanzadas sobre herramientas que pueden ayudar a resolver esto, especialmente las herramientas que podrían ayudarme a automatizar el cifrado querystring de una manera transparente. –

9

Bien, entonces quiero prologar mi respuesta con esto; Thomas claramente tiene la respuesta más precisa y completa hasta ahora para las personas que comienzan de cero. Esta respuesta no está en la misma línea en absoluto. Mi respuesta proviene del punto de vista del "desarrollador de negocios". Como todos sabemos demasiado bien; a veces no es factible gastar dinero reescribiendo algo que ya existe y "funciona" ... al menos no de una vez. A veces es mejor implementar una solución que le permita migrar a una mejor alternativa con el tiempo.

Lo único que diría que falta es Thomas; estado de javascript en el lado del cliente. Donde trabajo, hemos encontrado que los clientes esperan aplicaciones de tipo "Web 2.0" cada vez más. También descubrimos que este tipo de aplicaciones generalmente dan como resultado una satisfacción del usuario mucho mayor. Con un poco de práctica, y la ayuda de algunas bibliotecas de javascript realmente geniales como jQuery (incluso hemos empezado a utilizar GWT y descubrimos que es IMPRESIONANTE) la comunicación con los servicios REST basados ​​en JSON implementados en WCF puede ser trivial. Este enfoque también proporciona una forma muy agradable de comenzar a avanzar hacia una arquitectura basada en SOA, y una separación limpia de la interfaz de usuario y la lógica empresarial.

Pero estoy divagando.

Me parece que ya tiene una aplicación, y ya ha estirado los límites de la administración de estado de sesión integrada de ASP.NET. Así que ... esta es mi sugerencia (suponiendo que ya hayas probado la administración de sesión fuera de proceso de ASP.NET, que se escala significativamente mejor que la gestión de sesiones en proceso/en caja, y parece que lo hiciste porque has mencionado eso); NCache.

NCache le proporciona un reemplazo "sin cita previa" para las opciones de administración de sesiones de ASP.NET. Es súper fácil de implementar y podría ayudar a su aplicación más de una manera más que suficiente para ayudarlo a avanzar, sin ninguna inversión significativa en la refacturación de su base de código existente de inmediato.

Puede usar el tiempo y dinero extra para comenzar a reducir su deuda técnica enfocando el desarrollo en cosas con valor comercial inmediato, utilizando un nuevo enfoque (como cualquiera de las alternativas ofrecidas en las otras respuestas, o la mía) .

Sólo mis pensamientos.

+0

sw12345: He sw, gracias por la respuesta reflexiva. Lo acepté porque realmente es más el tipo de respuesta que estoy buscando: el resumen de Thomas de las diversas estrategias es exhaustivo, pero ya sabía que las cosas y el evento mencionaban mucho en mi pregunta real. Quería estrategias más avanzadas para investigar. ¡Gracias! –

3

Después de pasar por todos los escenarios y respuestas anteriores y este enlace Data pasing methods Mi consejo final sería:

GALLETAS para:

  • ENCRYPT [de ID de usuario]
  • ENCRYPT [ProductID]
  • ENCRIPTACIÓN [xyzIds ..]
  • ENCRYPT [etc.]

BASE DE DATOS para:

  • conjuntos de datos por ID COOKIE
  • DataTables ID de cookie
  • todos los otros grandes trozos POR ID de cookie

Mi consejo también depende de la continuación estadísticas y este enlace detalles Data pasing methods:

enter image description here

Cuestiones relacionadas