Posible duplicado:
escritura de aplicaciones web "sin servidor"
Entonces, digamos que voy a construir un clon de Stack Exchange y decido usar algo como CouchDB como mi tienda de back-end. Si utilizo su autenticación integrada y autorización a nivel de base de datos, ¿hay alguna razón para no permitir que el Javascript del lado del cliente escriba directamente en el servidor CouchDB disponible públicamente? Dado que esta es básicamente una aplicación CRUD y la lógica de negocios consiste en "Solo el autor puede editar su publicación". No veo mucha necesidad de tener una capa entre las cosas del lado del cliente y la base de datos. Simplemente usaría la validación en el lado CouchDB para asegurarme de que alguien no esté ingresando datos basura y asegúrese de que los permisos estén configurados correctamente para que los usuarios solo puedan leer sus propios datos de usuario. El renderizado se haría del lado del cliente por algo como AngularJS. En esencia, podría tener un servidor CouchDB y un montón de páginas "estáticas" y listo. No necesitaría ningún tipo de procesamiento del lado del servidor, solo algo que pudiera servir las páginas HTML.
Abrir mi base de datos al mundo parece incorrecto, pero en este escenario no puedo pensar por qué mientras los permisos estén configurados correctamente. Va en contra de mi instinto como desarrollador web, pero no puedo pensar en una buena razón. Entonces, ¿por qué es una mala idea?
EDITAR: Parece que hay una discusión similar aquí: escribir aplicaciones web "sin servidor"
EDITAR: ¡Increíble discusión hasta ahora, y agradezco los comentarios de todos! Siento que debería agregar algunas suposiciones genéricas en lugar de llamar específicamente a CouchDB y AngularJS. Entonces supongamos que:
- La base de datos puede autenticar usuarios directamente desde su tienda oculta
- Toda la comunicación de la base de datos se realizará a través de SSL
- La validación de datos puede (pero quizás no debería) ser manejada por la base de datos
- La única autorización que nos importa aparte de las funciones administrativas es que a alguien solo se le permita editar su propia publicación
- Estamos perfectamente de acuerdo con que todos puedan leer todos los datos (EXCEPTO los registros de usuarios que pueden contener hashes de contraseñas)
- Las funciones administrativas estarían restringidas por la autorización de la base de datos.
- Nadie puede agregarse a un rol de administrador
- La base de datos es relativamente fácil de escalar
- Hay poca o ninguna lógica comercial verdadera; esta es una aplicación CRUD básica
fuente
DELETE FROM ImportantData;
Respuestas:
Hacer lo que sugiere crea un acoplamiento estrecho (er) entre el idioma del lado del cliente y su base de datos.
Eso puede estar bien: hay menos código para escribir y mantener, y en teoría la depuración podría / debería ir un poco más rápido.
Por otro lado, hace que otros aspectos sean más difíciles. Si necesita cambiar cualquiera de esas tecnologías, tendrá más dificultades debido al estrecho acoplamiento entre ellas.
Protegerse contra los ataques será (bastante) un poco más difícil. Está asumiendo que el cliente siempre presentará solicitudes bien formateadas a la base de datos. Eso supone que nadie jamás hackeará el código del lado del cliente para insertar declaraciones maliciosas. En otras palabras, "tomarán prestados" sus mecanismos de autenticación y reemplazarán el código normal del cliente con el suyo.
No lo recomendaría, y muchos te dirían con vehemencia que no lo hagas. Pero se puede hacer.
fuente
Probablemente no sea una gran idea. Y la primera y más importante razón que puedo dar es que un servidor de base de datos no está diseñado para ser un servidor web público. Por el contrario, la sabiduría convencional dice que debe ocultar su base de datos detrás de un firewall.
Si necesita evidencia de apoyo, hay muchas preocupaciones, no todas insuperables, pero hay mucho en qué pensar. Sin ningún orden en particular, aquí hay algunos:
... Y estoy seguro de que hay otras preocupaciones. Y estoy seguro de que hay una solución para la mayoría, si no todas estas preocupaciones. ¡Pero hay una lista para comenzar!
fuente
La mejor razón que puedo imaginar es: porque este método no es directamente compatible o recomendado por ninguna de las partes involucradas.
Los proveedores de navegadores, los estándares EcmaScript, los desarrolladores de sistemas de bases de datos, las compañías de equipos de redes, los arquitectos de hosting / infraestructura y los especialistas en seguridad no respaldan activamente (o incluso consideran) su caso de uso propuesto. Esto es un problema, porque su método propuesto requiere que todas estas entidades, y más, funcionen adecuadamente para su aplicación, a pesar de que ninguno de los sistemas involucrados fue diseñado para soportar esto.
No digo que no sea posible. Solo digo que esto es menos como "reinventar la rueda" y más como reinventar la interacción cliente-servidor basada en el navegador.
En el mejor de los casos, hará un montón de trabajo para lograr que los sistemas funcionen al nivel más básico posible. Las bases de datos populares modernas no son RESTful ni están diseñadas para funcionar sobre HTTP, por lo que creará sus propios controladores de cliente basados en WebSocket (supongo).
Incluso si logra que todo funcione técnicamente, renunciará a muchas de las características más potentes de las arquitecturas modernas. No tendrá defensa en profundidad: todos pueden conectarse fácilmente directamente al objetivo principal de la mayoría de los intentos de piratería de sitios web. Pero el escenario que propone es mucho, mucho peor que eso.
El modelo propuesto no solo expone el servidor, sino que expone cadenas de conexión válidas. Los atacantes no pueden simplemente hacer ping al servidor, sino que pueden iniciar sesión activamente y alimentarlo con comandos. Incluso si puede limitar el acceso a los datos, no conozco suficientes herramientas en los sistemas DBMS para protegerlos de los escenarios de denegación de servicio y sus afines. Cuando se trabaja en versiones mejoradas de SQL, como TSQL, a menudo es trivialmente fácil producir bombas que funcionen de manera efectiva infinitamente (unas pocas uniones sin restricciones para producir un producto cartesiano y tendrás un SELECT que funcionará para siempre, haciendo un trabajo pesado) . Me imagino que necesitaría deshabilitar la mayoría de las características de SQL, incluso eliminar consultas básicas de SELECT con JOIN y quizás solo permitir llamar a procedimientos almacenados. Ni siquiera sé si puedes hacer eso, nunca me han pedido que lo intente. No lo hace
La escalabilidad de la base de datos también tiende a ser uno de los problemas más difíciles al trabajar a gran escala, mientras que escalar múltiples servidores HTTP, especialmente con páginas estáticas o en caché, es una de las partes más fáciles. Su propuesta hace que la base de datos haga más trabajo al ser responsable de básicamente el 100% de la actividad del lado del servidor. Esa es una falla asesina por sí sola. Lo que gana al mover el trabajo al cliente lo pierde al mover más trabajo a la base de datos.
Finalmente, me gustaría señalar que el corazón de lo que propones no es nuevo, sino que se remonta a décadas. Este modelo se llama el modelo de "base de datos fat", que básicamente movió la mayoría de la lógica del lado del servidor a la base de datos tal como lo propone. Hay muchas razones por las que ese modelo se ha dejado de lado en el Internet masivo, y probablemente sería informativo analizar más esa historia usted mismo. Tenga en cuenta también que, incluso entonces, se consideró poco tener usuarios completamente no confiables capaces de iniciar sesión en el sistema y ejecutar comandos, ya que el acceso aún se controlaría para seleccionar usuarios internos (conocidos) que no se suponía que atacaran el sistema constantemente.
El hecho es que aún necesitará un servidor HTTP para servir archivos, ya que los sistemas de bases de datos simplemente no lo hacen. Al mismo tiempo, todo lo que propone puede obtenerse utilizando un modelo de servidor delgado (como con Nodejs) para exponer una interfaz RESTful a su base de datos. Esto es popular por una razón: funciona, mantiene la base de datos oculta detrás de las capas de protección, es extremadamente escalable y, sin embargo, le permite construir su base de datos tan gruesa o tan delgada como desee.
fuente
Bueno, colocar su autorización (las preocupaciones de seguridad) y la validación lógica lejos de la base de datos proporciona una separación de las preocupaciones en su sistema de software. Por lo tanto, puede probar, mantener, escalar y reutilizar sus bloques de código lógico con menos riesgos de frenar la funcionalidad del sistema.
Proporcionar la capacidad de entrada del cliente para comunicarse directamente con la base de datos tiene un gran potencial para arruinar los datos .
Esto también significa que evitar / eliminar el acoplamiento estrecho hace que su sistema de software sea más fácil de mantener y SOLIDO.
fuente
Permitir que el usuario interactúe directamente con la base de datos me parece realmente peligroso.
¿Es el mecanismo de autenticación de CouchDB realmente tan sofisticado que puede aislar el acceso de lectura y escritura de un usuario solo a los datos que se supone que debe leer y escribir (estamos hablando de acceso por documento, quizás incluso por campo de documento) privilegios aquí)? ¿Qué pasa con los datos "comunales" que comparten varios usuarios? ¿No existe esto en absoluto en el diseño de su aplicación?
¿Realmente desea que el usuario pueda cambiar sus datos de CUALQUIER manera? ¿Qué pasa con las inyecciones de XSS, por ejemplo? ¿No sería mejor tener una capa de servidor para filtrarlos antes de que entren en la base de datos?
fuente
Has recibido una serie de razones, pero aquí hay una más: a prueba de futuro. Tarde o temprano, a medida que su aplicación evolucione, se le presentarán algunos requisitos que no se pueden lograr de manera fácil o segura en JS del lado del cliente o como un procedimiento almacenado en su base de datos.
Por ejemplo, le dicen que todos los registros nuevos deben tener una verificación CAPTCHA para ser válidos. Esto sería bastante fácil con casi cualquier marco de aplicación web moderno. Simplemente coloque un reCAPTCHA en el formulario de registro, devuelva el token de respuesta de reCAPTCHA al backend y agregue un par de líneas de código a su backend para verificar la validez del token con la API de Google (o mejor aún, use una biblioteca que otra persona escribió para hacerlo). para ti).
Si está utilizando un sistema de dos niveles y depende de la base de datos para toda su lógica del lado del servidor, ¿cómo va a verificar el token? Sí, supongo que podría ser teóricamente posible, dependiendo del DBMS, escribir un procedimiento almacenado que de alguna manera llame a un shell e invoque curl con los argumentos adecuados. Eso también es casi una idea horrible: el filtrado de entradas y la protección contra vulnerabilidades de seguridad serían terribles; tendrías un problema con el manejo de errores y los tiempos de espera; y tendrías que analizar la respuesta tú mismo. Sin mencionar que un DBMS no está destinado a hacer esto, por lo que no hay razón para pensar que el rendimiento, la estabilidad, la seguridad de los hilos, etc. no serán problemas. Vea, por ejemplo, este hilo , que analiza algunos de estos problemas para Postgres.
Y esos son solo los problemas relacionados con la adición de un CAPTCHA simple a un formulario. ¿Qué vas a hacer si deseas agregar la verificación por SMS, o un trabajo en segundo plano que envía correos electrónicos a usuarios inactivos para recordarles sobre tu aplicación, o agregar una función de carga de archivos para que las personas puedan configurar una foto de perfil? ¿Tal vez decidas que tu aplicación debería tener algunas pruebas automatizadas algún día? ¿O que desea realizar un seguimiento de los cambios en sus procedimientos en un sistema de control de versiones? Existen numerosas bibliotecas y herramientas para la mayoría de los idiomas útiles para manejar la mayoría de estas tareas por usted, pero pocas o ninguna estarán disponibles para su DBMS, porque no está destinado a hacer esto.
Eventualmente, querrá hacer algo que no pueda hacer directamente de manera razonable en su DBMS, y luego se quedará atrapado. Debido a que habrá creado toda su aplicación en su DBMS, no tendrá otra alternativa que obtener un servidor web y comenzar a reconstruir piezas en otro idioma, solo para agregar una función simple.
Y eso sería una verdadera lástima, porque ya tenemos un nombre para el lugar donde coloca la lógica de su aplicación, y se llama "código fuente de su aplicación" en lugar de "procedimientos almacenados en la base de datos" por una razón.
fuente
Si sus controles de seguridad y lógica de negocios están contenidos en su javascript del lado del cliente, un usuario malintencionado puede anularlos. Como alternativa, puede aprovechar una tecnología del lado del servidor basada en JavaScript (como Node.JS ) para manejar la validación, la autorización y similares.
fuente
Cualquier restricción comercial que desee garantizar debe validarse en el lado del servidor. Incluso si controla el acceso del usuario, alguien puede enviar datos no válidos.
Siguiendo su ejemplo de clonación stackoverflow:
Cualquiera podría manipular el código del lado del cliente y violar la integridad de los datos por completo (incluso si está restringido a ciertos objetos, como sus propias publicaciones).
fuente
Edite la página en Firebug y, en algún momento, coloque una línea similar a esta:
ExecDbCommand("DROP TABLE Users")
Ejecutarlo.
Editar:
La pregunta era, de hecho, sobre CounchDB, por lo que no es necesario ejecutar SQL. Sin embargo, la idea es la misma. Supongo que cualquier aplicación no trivial depende de los datos para respetar algunas reglas de coherencia que el código de la aplicación verifica / aplica. Un usuario malintencionado puede modificar el código del cliente para guardar los datos en una forma que viole las reglas de su negocio y pueda causar estragos en su aplicación.
Si su sitio considera que todos los estados de datos posibles son válidos desde una perspectiva comercial, entonces siga esta ruta, pero si este no es el caso (probablemente), entonces querrá tener la garantía de que cualquier información que se almacene sea generada por su código y de acuerdo a sus reglas .
fuente
Antigua pregunta, lo sé, pero quería intervenir porque mi experiencia es bastante diferente a las otras respuestas.
He pasado muchos años escribiendo aplicaciones colaborativas en tiempo real. El enfoque general para estas aplicaciones es replicar datos localmente y sincronizar los cambios con sus pares lo más rápido posible. Todas las operaciones en los datos son locales, por lo que todo el almacenamiento de datos, el acceso a los datos, la lógica empresarial y la interfaz de usuario son capas locales. El movimiento "fuera de línea primero" ( http://offlinefirst.org/ ) ha adoptado este enfoque para crear aplicaciones web fuera de línea y puede tener algunos recursos relevantes. ¡Este tipo de casos de uso no solo exige que abra su capa de acceso a datos a los clientes, sino también el almacenamiento de datos! Sé que sé. Parece una locura, ¿verdad?
Las preocupaciones por tales aplicaciones sin conexión primero son similares a lo que ha preguntado, solo un nivel eliminado. Me parece relevante. Dado que está abriendo el acceso directo a los datos a los clientes, la pregunta es, ¿cómo puede limitar los efectos de un usuario malintencionado? Bueno, hay muchas estrategias, pero no son obvias si vienes de un entorno de desarrollo más tradicional.
La primera idea errónea es que exponer la base de datos significa exponer todos los datos. Tome CouchDB por ejemplo; las bases de datos en CouchDB son livianas, por lo que no debería pensarlo dos veces en crear cientos de miles de bases de datos separadas en un servidor. Los usuarios solo pueden acceder a las bases de datos a las que se les ha otorgado permiso de acceso como lectores o escritores (y mucho menos las funciones de validación y demás de CouchDB), por lo que solo pueden acceder a un subconjunto de datos.
¡La segunda idea errónea es que un usuario que se queda sin datos es un problema! Si a los usuarios se les da una réplica de una base de datos, pueden cagarla todo lo que quieran sin afectar a otros usuarios. Pero, debe validar sus cambios antes de replicar sus datos nuevamente en la tienda "central". Piense en Git: los usuarios pueden hacer lo que quieran en sucursales, tenedores y repositorios locales sin afectar la rama maestra. La fusión con el maestro implica mucha ceremonia y no se hace a ciegas.
Actualmente estoy construyendo un sistema usando CouchDB donde los usuarios necesitan colaborar en los datos para construir un conjunto de datos que luego se "publica" a través de un flujo de trabajo QA / QC. La colaboración se lleva a cabo en una réplica de los datos (a esto le llamamos una base de datos provisional o de trabajo), y una vez completada, una persona responsable realiza QA / QC en los datos y solo después de eso se replica en el repositorio principal.
Muchos beneficios se derivan de esto, que son difíciles de lograr en otros sistemas, como el control de versiones, la replicación y la colaboración (¡deje que funcione sin conexión!) Para las aplicaciones CRUD de tres niveles tradicionales es superdifícil.
Mi consejo: si su aplicación es "tradicional", hágalo de la manera tradicional. Si alguna de las cosas que mencioné anteriormente (aunque hay muchas más ...) se aplica a usted, considere arquitecturas alternativas y prepárese para pensar lateralmente.
fuente
Creo que, dados todos sus supuestos, es factible ir directamente desde el cliente a la base de datos. Sin embargo, es razonable ver si sus suposiciones son válidas y es probable que lo sigan siendo en el futuro.
Me preocuparía que en el futuro podría no estar bien que todos leyeran todos los datos, y especialmente que podría desarrollar más lógica de negocios en el futuro. Ambos son más probables si el proyecto tiene éxito.
Siempre y cuando te dejes una forma de lidiar con estos problemas en el futuro cuando y si realmente necesites lidiar con ellos, creo que tu diseño funcionará. Creo que tendrá que tener mucho cuidado para separar las preocupaciones en el código JavaScript, y algunas de ellas podrían terminar reescritas en el servidor más adelante.
Pero definitivamente podría ver dónde podría valer la pena arriesgarse a hacer eso más tarde frente al beneficio de tener menos piezas móviles hoy.
fuente
En primer lugar, gracias por la pregunta FUERA DE LA CAJA .... :)
Pero lo que sugeriría es; Siempre trate de mantener una segregación entre sus 3 capas. que son Presentación / Negocio y Base de datos o DAO porque esa será la mejor práctica en ese tipo de requisitos y configuraciones donde habrá muchos cambios todos los días.
En mundos simples, su capa de presentación no debe conocer la capa de base de datos, es decir, el formato de algunos campos de tipo de fecha puede ser diferente de la capa de presentación y la capa de base de datos para que el usuario pueda tener la libertad de seleccionar el formato adecuado de la fecha según sus necesidades.
Y Business Logic debe actuar como un acoplamiento entre la capa de presentación y la base de datos / capa de Dao, como la conversión de los campos, algunas validaciones de negocios, etc. deben manejarse en la capa de negocios en lugar de en la sección de Javascript según su pregunta.
Esta segregación le proporcionará una gran facilidad y comportamiento durante escenarios complejos, funcionalidades e incluso validaciones complejas. La mejor ventaja es: puede tener diferentes tecnologías para implementar estas capas y se puede cambiar según las necesidades o el alcance del negocio.
Gracias
fuente
Si desea construir SQL en JavaScript y enviarlo a la base de datos, que verifica los derechos, etc., entonces, por razones de seguridad, sería un desastre. Simplemente porque cuando crea una API y crea consultas usted mismo, debe analizar desde el punto de vista de la seguridad solo el número limitado de consultas. Si las consultas se crean fuera de su sistema, tiene un número potencialmente ilimitado de trucos que alguien podría hacer.
Pero no es el caso ya que está utilizando una base de datos de valores clave (por lo que entiendo, CouchDB generalmente cae en esa categoría). La interfaz de la base de datos en sí es una especie de capa intermedia, y el equipo de Apache la prueba por razones de seguridad. Debido a la API de JavaScript relativamente simple, esto es aún más fácil de analizar para detectar posibles fallas que las interfaces tan complicadas que tienen las aplicaciones JSF.
Esta puede ser una solución segura si realiza pruebas de seguridad complejas. Esto puede ser aún más fácil como cuando se usan marcos como JSF, que a menudo usan API apenas legibles detrás. La seguridad por oscuridad no se considera una solución.
En relación con su pregunta, de todos modos no será acceso directo a la base de datos. El acceso directo sería la construcción de consultas SQL en JavaScript (desafortunadamente, he visto tales soluciones). En su caso, CouchDB proporciona la capa de aislamiento. Por supuesto, podría incluirlo en su API para endurecerlo, pero siempre que pueda probar fácilmente qué puede hacer un usuario en particular y si las restricciones de seguridad funcionan para usted, tendrá una solución segura y sólida sin capas adicionales.
fuente
Veo dos problemas:
1. Acoplamiento ajustado: ¿ Cambiar su opción de base de datos? Bueno, ahora también debes cambiar todo el código del lado del cliente. Créeme. No necesitamos más problemas en el lado del cliente.
2. Problema de seguridad de TMI: revela demasiado sobre cómo funcionan las cosas. La autenticación aún puede ser un obstáculo, pero encontrar un exploit es mucho más fácil cuando sabes exactamente lo que está sucediendo en el lado del servidor.
Un nivel medio muy delgado puede ser una mejor manera de hacerlo.
fuente
Su cliente no puede usar su aplicación web si javascript está deshabilitado (o no es compatible con el navegador de su dispositivo) si javascript es la única capa de acceso a la base de datos.
fuente