Tengo una aplicación web nodejs que usa el marco express y se puede acceder a ella a través de Internet. Estoy usando un almacén de sesiones que almacena las sesiones como archivos simples en el disco y, con la implementación actual, cada solicitud sin cookie obtendrá una nueva ID de sesión, lo que dará como resultado un nuevo archivo en el disco para la nueva sesión.
Dado que se puede acceder a la aplicación a través de Internet, recibo muchas solicitudes no válidas que, por supuesto, nunca envían cookies, pero producen más sesiones en mi sistema de archivos, lo cual es un verdadero desastre.
Usé la hoja de trucos de administración de sesiones de OWASP como guía para la implementación ( https://www.owasp.org/index.php/Session_Management_Cheat_Sheet ), pero no cubre el tema de las sesiones de invitados en detalle. Solo establece que las aplicaciones pueden encontrar útil asignar sesiones también a usuarios no autenticados (invitados), por lo que las sesiones de invitados parecen ser una característica válida en general.
Entonces, en este momento, no sé cómo combatir adecuadamente el problema de las sesiones/archivos de sesión creados innecesariamente por solicitudes no válidas/maliciosas. ¿Hay alguna forma recomendada de hacer esto?
Pensé en tal vez una combinación de una expiración muy corta de las sesiones de 'invitado' (< 5 minutos) y una lista blanca para rangos de IP o algo así, donde cualquier IP que no esté en la lista blanca no recibirá una sesión de invitado (pero por supuesto una sesión una vez autenticado con éxito).
¿Algún consejo sobre cómo debo abordar este problema?
Independientemente de cómo almacene su sesión, se enfrentará a este mismo problema. En algún momento, el almacenamiento de su sesión se desbordará (se quedará sin espacio en disco, se quedará sin RAM, se quedará sin inodos, etc.).
Lo que tienes que hacer es podar tus sesiones. A menos que realmente pueda permitirse el lujo de almacenar sesiones indefinidamente, debe establecer una fecha de caducidad en su cookie de sesión. Para el cliente el navegador se encargará de borrar la cookie. Para el servidor, debe verificar periódicamente todas las sesiones para ver si alguna ha caducado.
Lo que haces a continuación es simple. Independientemente de la tecnología que elija para almacenar sesiones, simplemente elimine las sesiones caducadas. Esto se puede hacer dentro de su proceso de nodo (dentro de algún controlador setTimeout() ) o fuera de su proceso de nodo (tal vez un simple trabajo cron diario).
Debe permitir un período de gracia (1 minuto, 1 hora, 1 día, etc.) antes de eliminar los archivos de sesión obsoletos para evitar una condición de carrera entre la eliminación del archivo de sesión y el usuario que carga el sitio web.
También puede permitir que los usuarios actualicen la fecha de vencimiento de la sesión en cada visita. Para un almacenamiento de sesiones basado en archivos, esto puede ser tan simple como tocar el archivo para actualizar la hora de la última modificación.
Hay una situación en la que esta estrategia no funcionará. Algunas bases de datos no liberarán espacio en disco cuando elimine datos por motivos de rendimiento (MySQL con InnoDB, por ejemplo). En cambio, los datos simplemente se marcan como eliminados, pero la base de datos sigue creciendo. En tales casos, su única salida es cambiar el almacenamiento de su sesión. Pero dado que está utilizando el almacenamiento de archivos, no es un problema del que deba preocuparse.
El mejor almacenamiento de sesión para su caso de uso sería Redis, Memcached o algún otro almacén de datos rápido en memoria, pero tenga en cuenta que todos los datos de su sesión deberán caber en la RAM.
Otra opción sería utilizar una base de datos basada en disco como cualquier RDBMS o Mongo, Couch, Rethink, etc., pero asegúrese de que sea rápida o, de lo contrario, su rendimiento se degradará enormemente.
La forma más rápida con las características de escalabilidad más altas sería no almacenar ningún dato de sesión en su servidor y, en cambio, confiar en los datos enviados en cookies u otro almacenamiento del lado del cliente, por ejemplo, usando JWT; consulte: https://jwt.io/ , pero tenga en cuenta que de esta manera no tendrá control sobre los tokens de sesión una vez emitidos a menos que introduzca una base de datos para verificar si son válidos o no y un mecanismo para invalidarlos, pero en este punto tiene los mismos problemas que con el almacenamiento de esos datos en el servidor , tal vez con la excepción de que potencialmente podría haber menos datos para almacenar y que no tendría que actualizarse con frecuencia.
Cada enfoque aquí tiene algunas ventajas y desventajas, pero el almacenamiento de datos en los archivos del sistema de archivos nunca es una solución óptima para la producción de ningún dato, no solo para los datos de la sesión. Debe usar una base de datos para eso o almacenar datos en el cliente si las desventajas de eso son aceptables en su caso de uso.
Esto es algo que quieres evitar:
app.use(session({ ... })); app.use(express.static(...));Eso crearía sesiones para todas las solicitudes estáticas.
Puede mitigar eso deshabilitando laconfiguración saveUninitialized :
app.use(session({ saveUninitialized : false, ... })); app.use(express.static(...));Eso evitará que se almacenen sesiones nuevas pero sin modificar. Debido a que los recursos estáticos no modifican las sesiones, no se crearán sesiones para ellos.
Otra opción sería habilitar sesiones solo para un subconjunto de sus rutas:
const session = require('express-session'); let sessionMiddleware = session({ ... }); app.use('/api', sessionMiddleware, apiRouter);