php - duracion - El controlador de la sesión de la cookie no guardará ningún error de validación o datos flash
session var laravel (2)
El controlador de sesión de cookies no es adecuado para aplicaciones que deben almacenar una cantidad significativa de datos en la sesión del usuario. Los navegadores generalmente limitan los datos almacenados en una cookie a alrededor de 4 KB (4096 bytes). Como descubrimos, podemos agotar fácilmente esta capacidad intentando almacenar una cadena de 1024 caracteres de longitud en la cookie de sesión; la cadena "Lorem ipsum ..." en la pregunta contiene solo caracteres ASCII, y cada carácter ASCII se representa usando 4 bytes, entonces 1024 × 4 = 4096 bytes.
Como podemos ver, rápidamente nos quedamos sin espacio cuando necesitamos almacenar elementos adicionales en una cookie de sesión, como los metadatos de serialización para valores PHP, o cuando los datos contienen caracteres UTF-8 que consumen más de 4 bytes por personaje. Para continuar usando cookies para almacenar datos de sesión de más de 4 KB, tendríamos que escribir un controlador de sesión personalizado que particione los datos de la sesión en múltiples cookies para cada respuesta y luego los reensamble en cada solicitud. Por una buena razón, ningún paquete existente hace esto que yo sepa. Esto me lleva a mi siguiente punto ...
Quiero desalentar firmemente el uso de cookies para almacenar una sesión completa (en lugar de solo una ID de sesión). Este enfoque puede exponer vulnerabilidades de seguridad, agrega sobrecarga a solicitudes y respuestas (incluidas solicitudes de activos estáticos en el mismo dominio), elimina la desincronización de datos (haga clic con el botón derecho en la aplicación → Duplicar para ver qué sucede), complica las pruebas y la depuración, y causa problemas al almacenar ciertos tipos de datos.
Para la aplicación distribuida en la pregunta, tenemos cuatro opciones:
- Almacene los datos de la sesión en un servidor central al que acceda cada instancia de la aplicación
- Almacenar el estado de la sesión en cada sitio y replicarlo entre sitios
- Use sesiones "adhesivas" para anclar a un usuario en un sitio después de comenzar una sesión
- Escriba una cantidad no trivial de código para implementar un controlador de sesión personalizado que permita al cliente pasar el estado de la sesión sin usar cookies, o una que particione cookies
Creo que podemos eliminar razonablemente la cuarta opción. A menos que tengamos una muy buena razón para evitar usar los primeros tres enfoques, y para las aplicaciones típicas que generalmente no lo hacemos, no podemos justificar la cantidad de trabajo, complejidad y sobrecarga necesarios para construir un sistema para transferir datos de sesión de un lado a otro HTTP cuando las primeras tres opciones son soluciones estándar y ampliamente aceptadas.
Basado en la información en la pregunta, me parece que ya comprende los conceptos y las implicaciones detrás de las otras tres opciones, por lo que no daré más explicaciones sobre cada una (pero haga un comentario para decirme si debería).
Para aplicaciones sin requisitos avanzados de infraestructura, recomiendo el tercer enfoque: sesiones adhesivas . Estos son relativamente fáciles de configurar y generalmente requieren configuración en el equilibrador de carga para que, una vez que un cliente inicie una sesión con un servidor de aplicaciones, el equilibrador de carga enrute cualquier solicitud subsiguiente al mismo servidor hasta que finalice la sesión. Para una alta disponibilidad, podemos combinar este enfoque con el controlador de sesión Redis y los servidores Redis configurados para la replicación maestro-esclavo entre los centros de datos y, opcionalmente, Redis Sentinel para automatizar la conmutación por error. Redis se adapta bien a los datos de sesión y ofrece un mejor rendimiento que una base de datos relacional. Si tenemos varias instancias de aplicaciones en cada centro de datos, Redis proporciona una ubicación central para los datos de sesión para todas las instancias en un sitio.
Para completar, y para responder directamente a la pregunta, aquí hay una descripción general del desarrollo necesario para crear un controlador de sesión basado en cookies que maneje datos de sesión de más de 4 KB. De nuevo, recomiendo uno de los otros enfoques descritos anteriormente:
Primero, necesitaremos crear una nueva clase que implemente
SessionHandlerInterface
de PHP (verifique el manejador de la sesión de cookies de Laravel para un punto de partida; probablemente podamos extender esta clase).El método
write()
de esta clase necesitará serializar los$data
la sesión y luego dividir los datos en fragmentos de menos de 4 KB (para algunos navegadores, menos de 4093 bytes). Asegúrese de dar cuenta de los caracteres multibyte. Antes de dividir los datos, también podemos encriptarlos si la sesión contiene información confidencial o si no queremos que los usuarios astutos entren en problemas con los valores. Luego, el método debería agregar una nueva cookie para cada fragmento de los datos de la sesión. Cada cookie deberá contener la secuencia en su nombre, y podemos agregar una cookie adicional que contenga la cantidad de fragmentos.El método
read()
realizará estas operaciones en reversa. Primero, reensamblará cada porción de las cookies en la solicitud utilizando el valor de la cookie que contiene la cantidad de fragmentos, y luego, opcionalmente, descifrará los datos si los encriptamos.El método
destroy()
debe borrar el contenido de cada cookie que contenga un fragmento.Luego, elegiremos un nombre para el controlador de la sesión, como
cookie-extended
, y, en el métodoboot()
un proveedor de servicios, registrarlo como un controlador disponible usando:Session::extend(''cookie-extended'', ...);
Tendremos que indicarle a la aplicación, en config / session.php o en .env , que use el nuevo controlador para las sesiones de usuario.
Si decides seguir este camino, asegúrate de probar la implementación en cada navegador que pienses apoyar, ya que los diferentes navegadores imponen sus propias limitaciones en el tamaño y la cantidad de cookies. Incluso si aumentamos la cantidad de datos de sesión que podemos almacenar como cookies, aún estamos limitados a la cantidad máxima de cookies que aceptará un navegador por dominio.
Como nota final, el almacenamiento de sesiones en la base de datos puede no afectar el rendimiento tanto como usted piensa. Podría valer la pena medir la carga real creada por esta solución simple antes de invertir muchas horas optimizando para una preocupación que podría no ser un problema real.
Estoy teniendo problemas con el controlador de sesión de cookies en Laravel.
Tengo un formulario simple con una validación en su lugar. Este es mi método para guardar los datos de este formulario:
public function store()
{
$this->validate(request(), [
''name'' => ''required'',
''title'' => ''required'',
''description'' => ''required|max:600'',
''image'' => ''required|file|mimes:jpeg,png'',
]);
$member = TeamMember::create(request()->all());
$member->addImage(request()->file(''image''));
return redirect()->route(''backoffice.team-members'');
}
Bastante simple.
El problema es que, al usar el controlador de sesión de cookie, si guardo este formulario con una descripción de 1024 caracteres de longitud, se me redireccionará, pero sin datos de actualización y sin $errors
en la vista para la siguiente solicitud.
Ejemplo:
Este es un POST después de usar esta línea:
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce gravida eros ut leo commodo luctus. Nulla neque dui, laoreet quis felis in, porta tincidunt felis. Phasellus in lacus et sem condimentum ornare. Praesent vitae nisi tempus, gravida tortor eu, convallis dui. Cras lacinia posuere scelerisque. Vestibulum tincidunt purus id sollicitudin varius. Sed eros urna, mattis nec nunc eu, finibus suscipit ipsum. Aliquam varius faucibus congue. Vivamus convallis imperdiet sem a commodo. Proin cursus feugiat sem a pharetra. Curabitur rhoncus non quam sit amet lacinia. Sed ut nisl id odio faucibus vehicula vel ut erat. Vestibulum ut iaculis magna. Quisque sit amet massa sodales, suscipit nisl eu, dapibus elit. Morbi posuere ligula pretium commodo semper. Nam odio elit, rutrum finibus tortor eget, viverra viverra metus. Proin tincidunt tempor ex pretium rhoncus. Proin egestas erat sed eros congue, mollis gravida magna bibendum. Pellentesque vel bibendum nunc. Orci varius natoque penatibus et magnis dis viverra fusce.
En el campo de descripción. 1024 bytes para ser exactos.
En cambio, si llego al campo con más datos ficticios pero nada demasiado loco:
Si cambio el controlador de sesión al archivo:
... funciona.
Pero esto no soluciona mi problema. Necesito usar el controlador de cookies para la sesión ya que el sitio web de producción se está ejecutando en 3 centros de datos diferentes para lograr una alta disponibilidad. El uso de la cookie para la sesión permite al usuario acceder a cualquiera de los 3 servidores y continuar con su solicitud sin tener que utilizar ninguna sesión fija ni ningún controlador de sesión central.
El uso de la base de datos como controlador, que también está en un clúster con HA, no es una opción, ya que este es un sitio web con mucho tráfico y sería una escritura por solicitud que no suena nada atractiva. Me gustaría evitar eso a toda costa.
De todos modos, esto se puede resolver?
Debo decir que este es el backoffice del sitio web, pero pronto el usuario en la interfaz también podrá escribir más de 1024 caracteres en un área de texto ... así que si solo cambio el controlador para el backoffice no ayuda, ya que nos encontraremos con lo mismo para nuestros usuarios.
El navegador tiene una limitación de cookie. Es demasiado grande para que el navegador almacene la cookie mientras usa cookie
como el controlador de sesión. Puede consultar la limitación de cookies del navegador aquí http://browsercookielimits.squawky.net/
Recomendación :
Use redis
como el controlador de sesión.
Pasos :
1.Después de instalar el servidor Redis , agregue el paquete predis/predis
:
composer require predis/predis
2. Cambie su archivo de configuración config/database.php
:
''redis'' => [
''client'' => ''predis'',
''default'' => [
''host'' => env(''REDIS_HOST'', ''localhost''),
''password'' => env(''REDIS_PASSWORD'', null),
''port'' => env(''REDIS_PORT'', 6379),
''database'' => 0,
],
],