Si se supone que las aplicaciones REST no tienen estado, ¿cómo gestiona las sesiones?

536

Necesito alguna aclaración. He estado leyendo sobre REST y creando aplicaciones RESTful. Según Wikipedia, REST en sí mismo se define como Transferencia de estado representacional . Por lo tanto, no entiendo todo este trago sin estado que todos siguen vomitando.

De wikipedia:

En cualquier momento en particular, un cliente puede estar en transición entre estados de aplicación o "en reposo". Un cliente en estado de reposo puede interactuar con su usuario, pero no crea carga y no consume almacenamiento por cliente en el conjunto de servidores o en la red.

¿Solo están diciendo que no use el almacén de datos de nivel de sesión / aplicación?

Entiendo que uno de los objetivos de REST es hacer que el acceso al URI sea coherente y esté disponible, por ejemplo, en lugar de ocultar las solicitudes de paginación dentro de las publicaciones, haciendo que el número de página de una solicitud forme parte del GET URI. Tiene sentido para mi. Pero parece que se está yendo por la borda diciendo que no se deben almacenar datos por cliente (datos de sesión) en el lado del servidor.

¿Qué pasaría si tuviera una cola de mensajes y mi usuario quisiera leerlos, pero a medida que los leía, quería bloquear los mensajes de ciertos remitentes que llegaban durante la sesión? ¿No tendría sentido almacenar esto en un lugar del lado del servidor y hacer que el servidor solo envíe mensajes (o ID de mensajes) que no hayan sido bloqueados por el usuario?

¿Realmente tengo que enviar la lista completa de remitentes de mensajes para bloquear cada vez que solicito la nueva lista de mensajes? La lista de mensajes pertinente para mí no debería ni debería ser un recurso disponible públicamente en primer lugar ...

De nuevo, solo trato de entender esto. Alguien por favor aclarar.


Actualizar:

He encontrado una pregunta de desbordamiento de pila que tiene una respuesta que no me llega hasta allí: cómo administrar el estado en REST que dice que el estado del cliente que es importante debe transferirse en cada solicitud ... Ugg .. parece un montón de gastos generales ... ¿Es esto correcto?

Zak
fuente
2
@ S.Lott: No creo que sea intencionalmente engañoso. Creo que es un malentendido debido a la terminología confusa.
SOLO MI OPINIÓN correcta
2
@ SOLO MI OPINIÓN correcta: Supongo interesante. Yo no podría creer tal cosa, ya que es obvio que "sin estado" significa que el protocolo REST en sí mismo no tiene estado; que no dice nada sobre el estado de la aplicación subyacente y lo actualiza con solicitudes PUT, POST y DELETE.
S.Lott
@ S.Lott: el protocolo HTTP en sí mismo no tiene estado. Por lo que hemos discutido a continuación, REST es un punto de vista de cómo construir su aplicación sin que el servidor web maneje el estado de la sesión (a diferencia de otros tipos de estado en cosas como el DB). Ni siquiera pensé que REST fuera un protocolo, sino más bien una vista sobre cómo usar el protocolo HTTP. Yo pensaba que ustedes limpiado hasta que era acerca de cómo construir su aplicación a escala por tener la tienda lado del cliente todos los datos de sesión específica del cliente, y haciendo URI accesos como idempotente como sea posible, excepto en los casos que no debe ser. Quizás no ... :(
Zak
1
"Quizás no ..." ¿Qué significa eso? ¿Tienes una nueva pregunta? Siéntase libre de buscar SO para ello. Si no existe aquí, entonces pregúntalo.
S.Lott
¿Alguien ha leído Reber de Webber, Parastatidis y Robinson en la práctica (o ha visto su ejemplo de restbucks)? Las respuestas a continuación tienen sentido, pero ¿seguramente los pedidos de café en el ejemplo restbucks son estatales sobre un cliente? El número de pedidos se escala con el número de clientes. ¿Dónde está la línea entre el estado del cliente y un recurso?
Rikki

Respuestas:

340

La apatridia significa que cada solicitud HTTP se realiza de forma completamente aislada. Cuando el cliente realiza una solicitud HTTP, incluye toda la información necesaria para que el servidor cumpla con esa solicitud. El servidor nunca se basa en información de solicitudes anteriores. Si esa información fuera importante, el cliente tendría que enviarla nuevamente en una solicitud posterior. La apatridia también trae nuevas características. Es más fácil distribuir una aplicación sin estado en servidores con equilibrio de carga. Una aplicación sin estado también es fácil de almacenar en caché.

En realidad, hay dos tipos de estado. Estado de aplicación que vive en el cliente y Estado de recurso que vive en el servidor.

Un servicio web solo necesita preocuparse por el estado de su aplicación cuando realmente está haciendo una solicitud. El resto del tiempo, ni siquiera sabe que existes. Esto significa que cada vez que un cliente realiza una solicitud, debe incluir todos los estados de la aplicación que el servidor necesitará para procesarla.

El estado de los recursos es el mismo para todos los clientes, y su lugar adecuado es en el servidor. Cuando carga una imagen en un servidor, crea un nuevo recurso: la nueva imagen tiene su propio URI y puede ser el objetivo de futuras solicitudes. Puede buscar, modificar y eliminar este recurso a través de HTTP.

Espero que esto ayude a diferenciar lo que significan la apatridia y los diversos estados.

Srikar Doddi
fuente
44
¿Significa esto que cada vez que se envía una solicitud, el cliente debe enviar su usuario / contraseña para autenticarse? Porque supongo que almacenar una sesión, incluso si está en una base de datos compartida no sql entre todos los servidores, no es apátrida, ¿o sí?
Carlos Navarro Astiasarán
1
@ CarlosNavarroAstiasarán existen varias técnicas para manejar la autenticación sin estado. Google JWT por ejemplo.
geoidésico
1
@geoidesic: "Debido a que los tokens web JSON no tienen estado, no hay forma de invalidarlos sin almacenar el estado del servidor, lo que anula la ventaja de los tokens sin estado". WIkipedia
ulatekh
@ulatekh Esa es una gran tergiversación de lo que puedes hacer con los tokens. Es bastante simple almacenar una ID aprobada junto con el token y aceptar solo tokens que tengan una ID aprobada como reclamo. Sin estado no significa que no puedas hacer algo en una base de datos. Esencialmente, almacena una ID en la base de datos que debe coincidir con la misma ID en el token. Para revocar el token, elimine la ID de la base de datos. Ningún estado se recuerda en el servicio en sí. O incluso mejor, guarde la clave de firma con el usuario en la base de datos y revoque la clave.
Andrew T Finnell el
@AndrewTFinnell: si tiene que almacenar la ID aprobada en el servidor, entonces debe almacenarse en todos los servidores potenciales que puedan procesar el inicio de sesión REST, lo que podría implicar una gran cantidad de estado del servidor en una arquitectura de servidor web masivamente paralela.
ulatekh
491

La explicación fundamental es:

No hay estado de sesión del cliente en el servidor.

Sin estado significa que el servidor no almacena ningún estado sobre la sesión del cliente en el lado del servidor.

La sesión del cliente se almacena en el cliente. El servidor no tiene estado significa que cada servidor puede atender a cualquier cliente en cualquier momento, no hay afinidad de sesión o sesiones fijas . La información de sesión relevante se almacena en el cliente y se pasa al servidor según sea necesario.

Eso no impide que otros servicios con los que habla el servidor web mantengan el estado sobre los objetos comerciales, como los carritos de compras, simplemente no sobre el estado actual de la aplicación / sesión del cliente.

El estado de la aplicación del cliente nunca debe almacenarse en el servidor, sino transmitirse del cliente a todos los lugares que lo necesiten.

De ahí proviene el ST en REST , Transferencia de Estado . Transfiere el estado en lugar de que el servidor lo almacene. Esta es la única forma de escalar a millones de usuarios concurrentes. Si no por otra razón que porque millones de sesiones son millones de sesiones.

La carga de la gestión de sesiones se amortiza en todos los clientes, los clientes almacenan su estado de sesión y los servidores pueden atender a muchos pedidos de magnitud o más clientes de forma apátrida.

Incluso para un servicio que cree que solo necesitará en los cientos de miles de usuarios simultáneos, aún debe hacer que su servicio sea apátrida. Decenas de miles sigue siendo decenas de miles y habrá costos de tiempo y espacio asociados con él.

Sin estado es la forma en que el protocolo HTTP y la web en general fueron diseñados para funcionar y es una implementación más simple en general y tiene una ruta de código única en lugar de un montón de lógica del lado del servidor para mantener un montón de estado de sesión.

Hay algunos principios de implementación muy básicos:

Estos son principios, no implementaciones, la forma en que cumple estos principios puede variar.

En resumen, los cinco principios clave son:

  1. Dar a cada "cosa" una identificación
  2. Une cosas juntas
  3. Utiliza métodos estándar
  4. Recursos con múltiples representaciones
  5. Comunícate sin estado

No hay nada sobre autenticación o autorización en la disertación REST .

Porque no hay nada diferente de autenticar una solicitud que es RESTful de una que no lo es. La autenticación es irrelevante para la discusión RESTful.

Explicar cómo crear una aplicación sin estado para sus requisitos particulares es demasiado amplio para StackOverflow.

Implementar la autenticación y la autorización en lo que respecta a REST es aún más amplio y varios enfoques para las implementaciones se explican con gran detalle en Internet en general.

Los comentarios que soliciten ayuda / información sobre esto solo se deben marcar como " Ya no es necesario" .


fuente
22
Parece una afirmación bastante audaz de que es la única forma de escalar a millones de usuarios. ¿Por qué las sesiones del lado del servidor no pueden ser solo otro servicio?
Zak
27
@Zak: Porque millones de sesiones son millones de sesiones. El punto es evitar la sobrecarga de toda esta gestión de sesión.
S.Lott
9191
no es audacia, es experiencia
21
Nada en mi respuesta implica una solución basada en el acceso a la base de datos en cada solicitud, si cree que lo hace, es un error de su parte entender la autenticación y la autorización a esa escala. La autenticación puede estar implícita en el estado, ¿crees que Facebook hace un "acceso a la base de datos" en cada solicitud de su API REST? ¿O Google para el caso? pista: no
66
Entonces, si almaceno el estado del usuario en un caché distribuido, digamos memcache, y todo mi servidor web ahora no necesita almacenar ningún estado sino ir y obtener el estado de memcache, ¿puedo considerar esta aplicación sin estado?
Jaskey
76

¿Solo están diciendo que no use el almacén de datos de nivel de sesión / aplicación?

No. No lo dicen de manera trivial.

Dicen que no defina una "sesión". No inicies sesión No cierre sesión. Proporcionar credenciales con la solicitud. Cada solicitud es independiente.

Aún tienes almacenes de datos. Aún tienes autenticación y autorización. Simplemente no pierde el tiempo estableciendo sesiones y manteniendo el estado de la sesión.

El punto es que cada solicitud (a) se mantiene completamente sola y (b) se puede cultivar trivialmente en una granja de servidores paralelos gigantes sin ningún trabajo real. Apache o Squid pueden pasar solicitudes RESTful a ciegas y con éxito.

¿Qué pasaría si tuviera una cola de mensajes y mi usuario quisiera leerlos, pero a medida que los leía, quería bloquear los mensajes de ciertos remitentes que llegaban durante la sesión?

Si el usuario quiere un filtro, simplemente proporcione el filtro en cada solicitud.

¿No tendría sentido ... que el servidor solo envíe mensajes (o ID de mensajes) que no hayan sido bloqueados por el usuario?

Si. Proporcione el filtro en la solicitud RESTful URI.

¿Realmente tengo que enviar la lista completa de remitentes de mensajes para bloquear cada vez que solicito la nueva lista de mensajes?

Si. ¿Qué tan grande puede ser esta "lista de remitentes de mensajes para bloquear"? ¿Una breve lista de PK?

Una solicitud GET puede ser muy grande. Si es necesario, puede probar una solicitud POST aunque parezca una especie de consulta.

S.Lott
fuente
28
"No inicie sesión. No cierre sesión. Proporcione credenciales con la solicitud". Siempre veo respuestas como esta en preguntas sobre cómo permanecer sin estado en una API REST sin ningún detalle sobre dónde / cómo se deben almacenar esas credenciales en el cliente. ¡Seguramente no deberíamos almacenar nombre de usuario y contraseña en el almacenamiento local!
BeniRose
2
@BeniRose, ¿no podemos almacenar un token en el almacenamiento local y usar ese token en solicitudes que identifiquen de forma única al usuario?
Nikhil Sahu
1
El almacenamiento local tiene muchas preocupaciones de seguridad por lo que entiendo. Pero también hay muchas otras preocupaciones con las sesiones del lado del cliente, como invalidar tokens, cerrar la sesión de un usuario, etc.
BeniRose
3
usa JWT que tiene una firma, la verificación de firma es rápida para que pueda verificar la validez de ese estado.
Arquímedes Trajano
36

Tiene toda la razón, admitir interacciones completamente sin estado con el servidor supone una carga adicional para el cliente. Sin embargo, si considera escalar una aplicación, el poder de cálculo de los clientes es directamente proporcional al número de clientes. Por lo tanto, escalar a un gran número de clientes es mucho más factible.

Tan pronto como asumas un poco de responsabilidad en el servidor para administrar cierta información relacionada con las interacciones de un cliente específico, esa carga puede crecer rápidamente para consumir el servidor.

Es una compensación.

Darrel Miller
fuente
32

Vista histórica de la gestión del estado de la aplicación del usuario

Las sesiones en el sentido tradicional mantienen el estado del usuario en la aplicación dentro del servidor. Esta puede ser la página actual en un flujo o lo que se ha ingresado previamente pero que aún no persiste en la base de datos principal.

La razón de esta necesidad fue la falta de estándares en el lado del cliente para mantener efectivamente el estado sin necesidad de hacer aplicaciones o complementos específicos del cliente (es decir, específicos del navegador).

La solicitud de encabezado HTML5 y XML ha estandarizado con el tiempo la noción de almacenar datos complejos, incluido el estado de la aplicación de manera estándar en el lado del cliente (es decir, el navegador) sin tener que recurrir al servidor.

Uso general de los servicios REST

Los servicios REST generalmente se llaman cuando hay una transacción que debe realizarse o si necesita recuperar datos.

Los servicios REST deben ser llamados por la aplicación del lado del cliente y no por el usuario final directamente.

Autenticando

Para cualquier solicitud al servidor, parte de la solicitud debe contener el token de autorización. La forma en que se implementa es específica de la aplicación, pero en general es una forma de autenticación BASICo una CERTIFICATE.

La autenticación basada en formularios no es utilizada por los servicios REST. Sin embargo, como se señaló anteriormente, los servicios REST no están destinados a ser llamados por el usuario, sino por la aplicación. La aplicación necesita administrar la obtención del token de autenticación. En mi caso, utilicé cookies con JASPIC con OAuth 2.0 para conectarme a Google para autenticación y autenticación HTTP simple para pruebas automatizadas. También utilicé la autenticación de encabezado HTTP a través de JASPIC para pruebas locales también (aunque el mismo enfoque se puede realizar en SiteMinder)

Según esos ejemplos, la autenticación se administra en el lado del cliente (aunque SiteMinder o Google almacenarían la sesión de autenticación en su extremo), no se puede hacer nada al respecto, pero no es parte de la aplicación de servicio REST.

Solicitudes de recuperación

Las solicitudes de recuperación en REST son GEToperaciones en las que se solicita un recurso específico y se puede almacenar en caché. No hay necesidad de sesiones de servidor porque la solicitud tiene todo lo que necesitaría para recuperar los datos: autenticación y el URI.

Guiones de transacciones

Como se señaló anteriormente, la propia aplicación del lado del cliente llama a los servicios REST junto con la autenticación que administra también en el lado del cliente.

Lo que esto significa para los servicios REST [si se hace correctamente] es llevar una sola solicitud al servidor REST que contendrá todo lo que se necesita para una operación de un solo usuario que haga todo lo que se necesita en una sola transacción, una secuencia de comandos de transacción es el patrón se llama.

Esto se hace POSTgeneralmente a través de una solicitud, pero PUTtambién se pueden usar otras como .

Muchos ejemplos artificiales de REST (yo mismo hice esto) intentaron seguir la mayor parte de lo que se ha definido en el protocolo HTTP, después de pasar por eso decidí ser más pragmático y lo dejé solo para GET y POST . El POSTmétodo ni siquiera tiene que implementar el patrón POST-REDIRECT-GET.

Sin embargo, como he señalado anteriormente, la aplicación del lado del cliente será la que llame al servicio y solo llamará a la POSTsolicitud con todos los datos cuando sea necesario (no siempre). Esto evita solicitudes constantes al servidor.

Votación

Aunque REST también se puede usar para sondeo, no lo recomendaré a menos que tenga que usarlo debido a la compatibilidad del navegador. Para eso usaría WebSockets para el que también había diseñado un contrato de API . Otra alternativa para navegadores antiguos es CometD.

Arquímedes Trajano
fuente
27

REST es muy abstracto. Es útil tener algunos ejemplos buenos, simples y del mundo real.

Tomemos, por ejemplo, todas las principales aplicaciones de redes sociales: Tumblr, Instagram, Facebook y Twitter. Todos tienen una vista de desplazamiento permanente donde cuanto más te desplazas hacia abajo, más contenido ves, más y más atrás en el tiempo. Sin embargo, todos hemos experimentado ese momento en el que pierdes a donde te desplazaron, y la aplicación te reinicia al principio. Por ejemplo, si cierra la aplicación, cuando la vuelve a abrir, vuelve a estar en la parte superior.

La razón es que el servidor no almacenó el estado de su sesión. Lamentablemente, su posición de desplazamiento se almacenó en la RAM del cliente.

Afortunadamente, no tiene que volver a iniciar sesión cuando se vuelve a conectar, pero eso es solo porque su certificado de inicio de sesión almacenado del lado del cliente no ha expirado. Elimine y vuelva a instalar la aplicación, y tendrá que volver a iniciar sesión, porque el servidor no asoció su dirección IP con su sesión.

No tiene una sesión de inicio de sesión en el servidor, ya que cumplen con REST.


Ahora, los ejemplos anteriores no incluyen un navegador web, pero en el back-end, las aplicaciones se comunican a través de HTTPS con sus servidores host. Mi punto es que REST no tiene que involucrar cookies y navegadores, etc. Hay varios medios para almacenar el estado de sesión del lado del cliente.

Pero hablemos de los navegadores web por un segundo, porque eso trae a colación otra ventaja importante de REST de la que nadie está hablando.

Si el servidor intentó almacenar el estado de la sesión, ¿cómo se supone que debe identificar a cada cliente individual?

No podía usar su dirección IP, porque muchas personas podrían estar usando esa misma dirección en un enrutador compartido. Entonces, ¿cómo?

No puede usar la dirección MAC por muchas razones, entre otras porque puede iniciar sesión en varias cuentas de Facebook diferentes simultáneamente en diferentes navegadores más la aplicación. Un navegador puede pretender fácilmente ser otro, y las direcciones MAC son tan fáciles de falsificar.

Si el servidor tiene que almacenar algún estado del lado del cliente para identificarlo, tiene que almacenarlo en la RAM por más tiempo que el tiempo necesario para procesar sus solicitudes, o de lo contrario tiene que almacenar en caché esos datos. Los servidores tienen cantidades limitadas de RAM y caché, sin mencionar la velocidad del procesador. El estado del lado del servidor se suma a los tres, exponencialmente. Además, si el servidor va a almacenar cualquier estado sobre sus sesiones, entonces debe almacenarlo por separado para cada navegador y aplicación con la que esté conectado actualmente, y también para cada dispositivo diferente que use.


Entonces ... espero que vean ahora por qué REST es tan importante para la escalabilidad. Espero que puedan comenzar a ver por qué el estado de la sesión del lado del servidor es para la escalabilidad del servidor lo que los yunques soldados son para la aceleración del automóvil.


Donde la gente se confunde es pensando que "estado" se refiere, como, a la información almacenada en una base de datos. No, se refiere a cualquier información que necesita estar en la RAM del servidor cuando la está usando.

Tostada de coma
fuente
13

Veo que el problema básico aquí es mezclar Session con State . Y aunque REST especifica que NO debe almacenar el estado en el servidor, nada le impide almacenar una sesión de usuario .

Administrar el estado en el servidor significa que su servidor sabe exactamente qué está haciendo el cliente (qué página está viendo en qué sección de la aplicación). Y esto es lo que no deberías necesitar hacer.

Estoy de acuerdo con las otras personas que dicen que debe mantener el almacenamiento de la sesión a un tamaño mínimo; y aunque eso es sentido común, en realidad también depende de la aplicación. En resumen, todavía puede mantener una sesión con datos en caché para manejar las solicitudes con menos carga en el servidor y administrar la autenticación al proporcionar un token de autenticación / acceso temporal para que el cliente lo use. Siempre que la sesión / token caduque, genere uno nuevo y pídale al cliente que lo use.

Alguien podría argumentar que el cliente debería generar mejor el token. Digo que funciona en ambos sentidos, y dependerá de la aplicación y de quién va a trabajar con la API.

También mantener algunos datos confidenciales de la sesión en el servidor debería ser la forma correcta de hacerlo. No puede confiar en el cliente para mantener su carrito de compras que (por ejemplo) contiene un campo llamado "isFreeGift". Dicha información debe mantenerse en el servidor.

El enlace de video proporcionado por Santanu Dey en su respuesta es útil. Míralo si no lo has hecho.

Solo una nota al margen: Parece que todas las respuestas ya dadas parecen ignorar el hecho de que algunas operaciones podrían causar una gran carga en el servidor. Eso es relevante en términos de consumo de energía, consumo de hardware y costo (para servidores alquilados por ciclo de CPU). Un buen desarrollador no debería ser flojo para optimizar su aplicación, incluso si la operación se puede hacer muy rápidamente en una CPU moderna en algún servidor alquilado por el que no paga su factura de electricidad y mantenimiento.

A pesar de que la pregunta tiene algunos años, espero que mi respuesta siga siendo útil.

Sam Sirry
fuente
44
En general, estoy de acuerdo con este sentimiento, pero ha habido una tendencia reciente a afirmar que incluso un identificador de sesión no debe almacenarse en el servidor. Todavía no he descubierto cuál es la solución alternativa, JWT es muy promocionado, pero viene con un puñado de trucos
BeniRose
11

Sin estado significa que el estado del servicio no persiste entre solicitudes y respuestas posteriores. Cada solicitud lleva sus propias credenciales de usuario y se autentica individualmente. Pero en estado, cada solicitud se conoce de cualquier solicitud previa. Todas las solicitudes con estado están orientadas a la sesión, es decir, cada solicitud debe conocer y retener los cambios realizados en solicitudes anteriores.

La aplicación bancaria es un ejemplo de aplicación con estado. Donde el usuario primero inicia sesión, luego realiza la transacción y cierra la sesión. Si después de cerrar sesión, el usuario intentará realizar la transacción, no podrá hacerlo.

Sí, el protocolo http es esencialmente un protocolo sin estado, pero para que tenga estado, nos hacemos cookies HTTP. Entonces, es SOAP por defecto. Pero también se puede hacer con estado, depende del marco que esté utilizando.

HTTP no tiene estado, pero aún así podemos mantener la sesión en nuestra aplicación Java utilizando diferentes mecanismos de seguimiento de sesión.

Sí, también podemos mantener la sesión en el servicio web, ya sea REST o SOAP. Se puede implementar mediante el uso de cualquier biblioteca de terceros o puede implementarlo por nuestra cuenta.

Tomado de http://gopaldas.org/webservices/soap/webservice-is-stateful-or-stateless-rest-soap

Ata ul Mustafa
fuente
11

No hay cuchara.

No pienses en la apatridia como "enviar todas tus cosas al servidor una y otra vez". De ninguna manera. Siempre habrá un estado: la base de datos en sí es un tipo de estado, después de todo, usted es un usuario registrado, por lo que cualquier conjunto de información del lado del cliente no será válido sin el lado del servidor. Técnicamente, nunca eres realmente apátrida.

Una palabra en el debate de inicio de sesión cada vez

¿Qué significa incluso no mantener una sesión e iniciar sesión cada vez? Algunos significan "enviar la contraseña cada vez", eso es simplemente estúpido. Algunos dicen "no, por supuesto que no, envíe un token en su lugar" - he aquí, la sesión PHP está haciendo casi exactamente eso. Envía una identificación de sesión que es una especie de token y te ayuda a llegar a tus cosas personales sin reenviar u / pw cada vez. También es bastante confiable y está bien probado. Y sí, conveniente, que puede convertirse en un inconveniente, vea el siguiente párrafo.

Reduce la huella

Lo que debe hacer , en cambio, y lo que tiene sentido, es reducir al mínimo la huella de su servidor web. Los lenguajes como PHP hacen que sea muy fácil simplemente guardar todo en el almacenamiento de la sesión, pero las sesiones tienen un precio. Si tiene varios servidores web, deben compartir la información de la sesión, porque también comparten la carga; cualquiera de ellos puede tener que atender la próxima solicitud.

Un almacenamiento compartido es imprescindible. El servidor necesita saber al menos si alguien ha iniciado sesión o no. (Y si molesta la base de datos cada vez que necesita decidir esto, está prácticamente condenado). Los almacenamientos compartidos deben ser mucho más rápidos que la base de datos. Esto trae la tentación: está bien, tengo un almacenamiento muy rápido, ¿por qué no hacer todo allí? - Y ahí es donde las cosas se ponen feas de otra manera.

Entonces, ¿estás diciendo, mantener el almacenamiento de sesión al mínimo?

De nuevo, es tu decisión. Puede almacenar cosas allí por razones de rendimiento (la base de datos es casi siempre más lenta que Redis), puede almacenar información de forma redundante, implementar su propio almacenamiento en caché, lo que sea, solo tenga en cuenta que los servidores web tendrán una carga mayor si almacena mucha basura. en ellos. Además, si se rompen bajo cargas pesadas (y lo harán), perderá información valiosa; con la forma de pensar REST, todo lo que sucede en este caso es que el cliente envía la misma solicitud (!) nuevamente y esta vez se la atiende.

¿Cómo hacerlo bien entonces?

No hay una solución única aquí. Yo diría que elija un nivel de apatridia y vaya con eso. Las sesiones pueden ser amadas por algunos y odiadas por otros, pero no van a ninguna parte. Con cada solicitud, envíe tanta información como tenga sentido, quizás un poco más; pero no interpretes la apatridia como no tener una sesión, ni como iniciar sesión cada vez. De alguna manera, el servidor debe saber que eres tú ; Los identificadores de sesión PHP son una buena forma, los tokens generados manualmente son otra.

Piensa y decide, no dejes que las tendencias de diseño piensen por ti.

dkellner
fuente
1
"Piensa y decide, no dejes que las tendencias de diseño piensen por ti". Desafortunadamente, hoy en día es muy común seguir estúpidamente las tendencias. A veces, al leer SO obtendrás las mismas respuestas solo por la tendencia.
lk
Sí, he visto esto en muchos temas y cuando me doy cuenta de lo que está sucediendo, a veces dejo de discutir. En aquel entonces, todos estaban locos por cómo Content-Box es mejor que Border-Box; Era una forma de mostrar odio contra IE. Luego vino el arranque y, de repente, todos creían en la frontera. Las tendencias vienen pero luego se van. Use goto, use tablas, use iframes, solo sepa lo que está haciendo y por qué. Las tendencias intentarán derribarte, luego se registrarán y pagarán en tu sitio. Mundo salvado de nuevo.
dkellner el
@dkellner No entendí esa parte: "El servidor necesita saber al menos si alguien ha iniciado sesión o no. (Y si molesta la base de datos cada vez que necesita decidir esto, está prácticamente condenado)". Supongamos que almacena datos de sesión en la base de datos con PHP. ¿Por qué la consulta de la base de datos para el inicio de sesión es incorrecta (condenado es una palabra fuerte) ya que de todos modos habrá muchas solicitudes de base de datos posteriores para obtener los datos completos del usuario y otras cosas, en función de la ID de la sesión de PHP? En otras palabras, las consultas DB son inevitables en cualquier caso. Además, si no recibe una ID de sesión PHP, sabe que el usuario no está autenticado, no es necesario consultar.
user2923322
Cuando tienes miles o incluso millones de usuarios, no puedes permitirte el lujo de conectarte a db cada vez que deseas realizar una actualización en vivo, una actualización de ubicación, una encuesta de mensajes o cualquier cosa que necesite un breve registro. Debe implementar estas llamadas sin (o con un mínimo) acceso a la base de datos, por eso digo que puede ser letal si construye todo su concepto alrededor de db. Una vez más, puede haber casos en los que una solución db bien diseñada funcionará, pero el programador típico resolverá cualquier cosa diciendo "está bien, primero nos conectamos y buscamos información del usuario". Baaaad practica.
dkellner
3

La principal diferencia entre sin estado y con estado es que los datos se devuelven al servidor cada vez. En caso de estado, el cliente debe proporcionar toda la información, por lo que es posible que se deban pasar muchos parámetros en cada solicitud. En Stateful, el cliet pasa esos parámetros una vez y el servidor los mantiene hasta que el cliente los modifique nuevamente.

En mi opinión, la API no debe tener estado, lo que permite escalar realmente rápido.

psuhas
fuente
2

Debe administrar la sesión del cliente en el lado del cliente. Esto significa que debe enviar datos de autenticación con cada solicitud, y probablemente, pero no necesariamente, tenga una memoria caché en memoria en el servidor, que empareje los datos de autenticación con la información del usuario como identidad, permisos, etc.

Esta restricción de apatridia REST es muy importante. Sin aplicar esta restricción, su aplicación del lado del servidor no se escalará bien, porque mantener cada sesión de cliente será el talón de Aquiles .

inf3rno
fuente
Si envía datos de autenticación con cada solicitud, ¿dónde / cómo almacena las credenciales en el cliente para que el usuario no tenga que volver a ingresarlas en cada solicitud?
Ámbar
1

Cuando desarrolle un servicio RESTful, para iniciar sesión necesitará que su usuario se autentique. Una posible opción sería enviar el nombre de usuario y la contraseña cada vez que intente realizar una acción del usuario. En este caso, el servidor no almacenará datos de sesión en absoluto.

Otra opción es generar un ID de sesión en el servidor y enviarlo al cliente, para que el cliente pueda enviar el ID de sesión al servidor y autenticarse con eso. Esto es mucho más seguro que enviar el nombre de usuario y la contraseña cada vez, ya que si alguien obtiene esos datos, puede suplantar al usuario hasta que se cambien el nombre de usuario y la contraseña. Puede decir que incluso la identificación de la sesión puede ser robada y el usuario será suplantado en ese caso y tiene razón. Sin embargo, en este caso, suplantar al usuario solo será posible mientras la identificación de la sesión sea válida.

Si la API RESTful espera un nombre de usuario y una contraseña para cambiar el nombre de usuario y la contraseña, incluso si alguien se hizo pasar por el usuario utilizando la identificación de la sesión, el hacker no podrá bloquear al usuario real.

Se podría generar un id de sesión mediante el bloqueo unidireccional (cifrado) de algo que identifica al usuario y agregando el tiempo al id de sesión, de esta manera se podría definir el tiempo de caducidad de la sesión.

El servidor puede o no almacenar identificadores de sesión. Por supuesto, si el servidor almacena la identificación de la sesión, violaría los criterios definidos en la pregunta. Sin embargo, solo es importante asegurarse de que la identificación de la sesión se pueda validar para el usuario dado, lo que no necesita almacenar la identificación de la sesión. Imagine una forma en que tiene una encriptación unidireccional de correo electrónico, identificación de usuario y algunos datos privados específicos del usuario, como el color favorito, este sería el primer nivel y de alguna manera agregaría la fecha de nombre de usuario a la cadena encriptada y aplicaría dos Cifrado de forma. Como resultado, cuando se recibe un ID de sesión, el segundo nivel podría descifrarse para poder determinar qué nombre de usuario dice ser el usuario y si el tiempo de sesión es el correcto. Si esto es válido, entonces el primer nivel de cifrado podría validarse haciendo ese cifrado nuevamente y verificando si coincide con la cadena. No necesita almacenar datos de sesión para lograrlo.

Lajos Arpad
fuente
esto tiene sentido
comenzó el
0

Todo el concepto es diferente ... No necesita administrar sesiones si está tratando de implementar el protocolo RESTFul. En ese caso, es mejor realizar el procedimiento de autenticación en cada solicitud (mientras que tiene un costo adicional en términos de rendimiento; la contraseña de hash sería un buen ejemplo. No es un gran problema ...). Si usa sesiones, ¿cómo puede distribuir la carga en varios servidores? Apuesto a que el protocolo RESTFul está destinado a eliminar las sesiones de cualquier tipo, realmente no las necesita ... Es por eso que se llama "sin estado". Las sesiones solo se requieren cuando no puede almacenar otra cosa que no sea Cookie en el lado del cliente después de que se haya realizado una solicitud (tome como ejemplo un navegador antiguo que no sea compatible con Javascript / HTML5). En el caso del cliente RESTFul "con todas las funciones", generalmente es seguro almacenarbase64(login:password) en el lado del cliente (en la memoria) hasta que la aplicación todavía esté cargada: la aplicación se usa para acceder al único host y la cookie no puede verse comprometida por los scripts de terceros ...

Recomiendo encarecidamente deshabilitar la autenticación de cookies para los servicios RESTFul ... consulte Autenticación básica / implícita, eso debería ser suficiente para los servicios basados ​​en RESTFul.

usuario3857922
fuente
3
¿Qué es a client side (in memory) y cómo es seguro ahorrar base64(login:password)en el lado del cliente?
RN Kushwaha
1
Nada se define como "completamente seguro". Sin embargo, puede considerar usar OAuth2 que proporciona una mejor seguridad que guardar la cadena base64 para la solicitud de API (autenticación básica), si se queda en la autenticación básica, puede usar HTTPS para una mejor seguridad.
felixwcf
3
RN Kushwaha, esta es la pregunta que nadie parece querer responder cuando le dicen que deje de almacenar la sesión en el servidor y la almacene en el cliente.
BeniRose
0

REST no tiene estado y no mantiene ningún estado entre las solicitudes. Las cookies / encabezados del cliente están configuradas para mantener el estado del usuario como la autenticación. Digamos que el nombre de usuario / contraseña del Cliente son validados por un mecanismo de autenticación de terceros: germinación de OTP de segundo nivel, etc. Una vez que el usuario se autentica, los encabezados / cookies se detienen y el punto final del servicio queda expuesto y podemos asumir que el usuario está autenticado ya que el usuario viene con encabezados / cookies válidos . Ahora, cierta información del usuario, como IP, se mantiene en la memoria caché y, luego, si la solicitud proviene del mismo IP (dirección mac) para los recursos enumerados, se permite al Usuario. Y la memoria caché se mantiene durante un tiempo particular que se invalida una vez que transcurre el tiempo. Por lo tanto, se puede usar la memoria caché o las entradas de la base de datos para mantener la información en blanco y negro de las solicitudes.

Amit
fuente
0

Sin estado aquí significa que el estado o metadatos de la solicitud no se mantienen en el lado del servidor. Al mantener cada solicitud o estado del usuario en el servidor, se generarían cuellos de botella en el rendimiento. El servidor solo se solicita con los atributos requeridos para realizar cualquier operación específica.

Para administrar las sesiones, o para dar una experiencia personalizada a los usuarios, es necesario mantener algunos metadatos o el estado de las preferencias del usuario, el historial de solicitudes anteriores. Esto se puede hacer manteniendo cookies, atributos ocultos o en objetos de sesión.

Esto puede mantener o realizar un seguimiento del estado del usuario en la aplicación.

¡Espero que esto ayude!

Sourabh Bhavsar
fuente