¿Las sesiones realmente violan RESTfulness?

¿El uso de sesiones en una API RESTful realmente viola la RESTfulness? He visto muchas opiniones en cualquier dirección, pero no estoy convencido de que las sesiones sean RESTless . Desde mi punto de vista:

  • la autenticación no está prohibida para RESTfulness (de lo contrario, habría poco uso en los servicios RESTful)
  • la autenticación se realiza mediante el envío de un token de autenticación en la solicitud, generalmente el encabezado
  • este token de autenticación necesita ser obtenido de alguna manera y puede ser revocado, en cuyo caso debe ser renovado
  • el token de autenticación debe ser validado por el servidor (de lo contrario, no sería la autenticación)

Entonces, ¿cómo las sesiones violan esto?

  • las sesiones del lado del cliente se realizan utilizando cookies
  • las cookies son simplemente un encabezado HTTP adicional
  • una cookie de sesión puede ser obtenida y revocada en cualquier momento
  • las cookies de sesión pueden tener un tiempo de vida infinito si es necesario
  • la identificación de la sesión (token de autenticación) está validada en el lado del servidor

Como tal, para el cliente, una cookie de sesión es exactamente la misma que cualquier otro mecanismo de autenticación basado en encabezado HTTP, excepto que usa el encabezado Cookie lugar de la Authorization o algún otro encabezado propietario. Si no había sesión asociada al valor de cookie en el servidor, ¿por qué marcaría la diferencia? La implementación del lado del servidor no necesita preocuparse del cliente mientras el servidor se comporte RESTful. Como tal, las cookies por sí mismas no deben hacer una API RESTless , y las sesiones son simplemente cookies para el cliente.

¿Mis suposiciones están equivocadas? ¿Qué hace que las cookies de sesión RESTless ?

Primero, definamos algunos términos:

  • Sosegado:

    Uno puede caracterizar aplicaciones que se ajusten a las restricciones REST descritas en esta sección como “RESTful”. [15] Si un servicio infringe alguna de las restricciones requeridas, no se puede considerar RESTful.

    de acuerdo con wikipedia .

  • restricción sin estado:

    A continuación, añadimos una restricción a la interacción cliente-servidor: la comunicación debe ser de naturaleza sin estado, como en el estilo cliente-servidor sin estado (CSS) de la Sección 3.4.3 (Figura 5-3), de modo que cada solicitud del cliente a el servidor debe contener toda la información necesaria para comprender la solicitud y no puede aprovechar el contexto almacenado en el servidor. Por lo tanto, el estado de la sesión se mantiene completamente en el cliente.

    de acuerdo con la disertación Fielding .

Así que las sesiones del lado del servidor violan la restricción sin estado de REST, y por lo tanto RESTfulness.

Como tal, para el cliente, una cookie de sesión es exactamente la misma que cualquier otro mecanismo de autenticación basado en encabezado HTTP, excepto que usa el encabezado Cookie en lugar de la autorización o algún otro encabezado propietario.

Con las cookies de sesión, almacena el estado del cliente en el servidor y, por lo tanto, su solicitud tiene un contexto. Intentemos agregar un equilibrador de carga y otra instancia de servicio a su sistema. En este caso, debe compartir las sesiones entre las instancias de servicio. Es difícil mantener y extender dicho sistema, por lo que escasea mal …

En mi opinión, no hay nada de malo con las cookies. La tecnología de cookies es un mecanismo de almacenamiento del lado del cliente en el que los datos almacenados se adjuntan automáticamente a los encabezados de las cookies en cada solicitud. No sé de una restricción REST que tenga problemas con ese tipo de tecnología. Entonces no hay problema con la tecnología en sí, el problema es con su uso. Fielding escribió una subsección sobre por qué cree que las cookies HTTP son malas.

Desde mi punto de vista:

  • la autenticación no está prohibida para RESTfulness (de lo contrario, habría poco uso en los servicios RESTful)
  • la autenticación se realiza mediante el envío de un token de autenticación en la solicitud, generalmente el encabezado
  • este token de autenticación necesita ser obtenido de alguna manera y puede ser revocado, en cuyo caso debe ser renovado
  • el token de autenticación debe ser validado por el servidor (de lo contrario, no sería la autenticación)

Tu punto de vista fue bastante sólido. El único problema fue con el concepto de crear token de autenticación en el servidor. No necesitas esa parte. Lo que necesita es almacenar el nombre de usuario y la contraseña en el cliente y enviarla con cada solicitud. No necesita más para hacer esto que HTTP auth auth y una conexión cifrada:

Figura 1. - Autenticación sin estado por clientes de confianza

  • Figura 1. – Autenticación sin estado por clientes de confianza

Probablemente necesite una memoria caché de autenticación en la memoria del lado del servidor para agilizar las cosas, ya que debe autenticar cada solicitud.

Ahora, esto funciona bastante bien con clientes de confianza que usted haya escrito, pero ¿qué pasa con los clientes de terceros? No pueden tener el nombre de usuario y la contraseña, ni todos los permisos de los usuarios. Por lo tanto, debe almacenar por separado los permisos que un cliente externo puede tener por un usuario específico. De modo que los desarrolladores del cliente pueden registrar clientes de terceros y obtener una clave de API única y los usuarios pueden permitir que terceros clientes accedan a una parte de sus permisos. Como leer el nombre y la dirección de correo electrónico, o enumerar a sus amigos, etc. Después de permitir un cliente externo, el servidor generará un token de acceso. Este token de acceso puede ser utilizado por el cliente de terceros para acceder a los permisos otorgados por el usuario, así:

Figura 2. - Autenticación sin estado por clientes de terceros

  • Figura 2. – Autenticación sin estado por clientes de terceros

Entonces, el cliente externo puede obtener el token de acceso de un cliente de confianza (o directamente del usuario). Después de eso, puede enviar una solicitud válida con la clave API y el token de acceso. Este es el mecanismo de autenticación de terceros más básico. Puede leer más sobre los detalles de implementación en la documentación de cada sistema de autenticación de terceros, por ejemplo, OAuth. Por supuesto, esto puede ser más complejo y más seguro, por ejemplo, puede firmar los detalles de cada solicitud en el servidor y enviar la firma junto con la solicitud, y así sucesivamente … La solución real depende de la necesidad de su aplicación.

En primer lugar, REST no es una religión y no debe abordarse como tal. Si bien existen ventajas para los servicios RESTful, solo debe seguir los principios de REST en la medida en que tengan sentido para su aplicación.

Dicho esto, la autenticación y el estado del lado del cliente no violan los principios de REST. Si bien REST requiere que las transiciones de estado sean sin estado, esto se refiere al servidor en sí. En el fondo, todo REST es sobre documentos. La idea detrás de la apatridia es que el SERVIDOR es apátrida, no los clientes. Cualquier cliente que emita una solicitud idéntica (los mismos encabezados, cookies, URI, etc.) debe llevarse al mismo lugar en la aplicación. Si el sitio web almacenaba la ubicación actual del usuario y la navegación administrada actualizando esta variable de navegación del lado del servidor, entonces se violaría REST. Otro cliente con información de solicitud idéntica sería llevado a una ubicación diferente dependiendo del estado del lado del servidor.

Los servicios web de Google son un fantástico ejemplo de un sistema RESTful. Requieren un encabezado de autenticación con la clave de autenticación del usuario que se aprobará en cada solicitud. Esto viola ligeramente los principios de REST, porque el servidor está rastreando el estado de la clave de autenticación. El estado de esta clave debe mantenerse y tiene algún tipo de fecha / hora de vencimiento después de lo cual ya no otorga acceso. Sin embargo, como mencioné en la parte superior de mi publicación, se deben hacer sacrificios para permitir que una aplicación realmente funcione. Dicho esto, los tokens de autenticación deben almacenarse de manera que permita a todos los clientes posibles continuar otorgando acceso durante sus horas válidas. Si un servidor está administrando el estado de la clave de autenticación hasta el punto de que otro servidor con equilibrio de carga no puede asumir el cumplimiento de las solicitudes basadas en esa clave, ha comenzado a violar realmente los principios de REST. Los servicios de Google aseguran que, en cualquier momento, puede tomar un token de autenticación que estaba usando en su teléfono contra el servidor de equilibrio de carga A y acceder al servidor B de saldo de carga desde su escritorio y seguir teniendo acceso al sistema y dirigirse a los mismos recursos si las solicitudes fueron idénticas.

Lo que todo se reduce a esto es que debes asegurarte de que tus tokens de autenticación se validan contra un almacén de respaldo de algún tipo (base de datos, caché, lo que sea) para asegurarte de que conservas tantas propiedades de REST como sea posible.

Espero que todo eso tenga sentido. También debe consultar la sección Restricciones del artículo de wikipedia sobre Representational State Transfer si aún no lo ha hecho. Es particularmente esclarecedor con respecto a lo que los principios de REST están realmente argumentando y por qué.

Las cookies no son para autenticación. ¿Por qué reinventar una rueda? HTTP tiene mecanismos de autenticación bien diseñados. Si utilizamos cookies, caemos en el uso de HTTP como un protocolo de transporte únicamente, por lo tanto, necesitamos crear nuestro propio sistema de señalización, por ejemplo, para decirle a los usuarios que proporcionaron una autenticación incorrecta (usar HTTP 401 sería incorrecto ya que probablemente no lo hagamos). suministrar Www-Authenticate a un cliente, ya que las especificaciones HTTP requieren :)). También se debe tener en cuenta que Set-Cookie es solo una recomendación para el cliente. Sus contenidos pueden guardarse o no (por ejemplo, si las cookies están desactivadas), mientras que el encabezado de Authorization se envía automáticamente en cada solicitud.

Otro punto es que, para obtener una cookie de autorización, es probable que desee proporcionar sus credenciales en algún lugar primero. Si es así, ¿no sería RESTless? Ejemplo simple:

  • Intenta obtener GET /a sin cookies
  • Usted recibe una solicitud de autorización de alguna manera
  • Vas y autorizas de alguna manera como POST /auth
  • Obtienes Set-Cookie
  • Intenta obtener GET /a con cookie. ¿Pero GET /a comporta de manera ideopotente en este caso?

Para resumir, creo que si accedemos a algún recurso y necesitamos autenticarnos, entonces debemos autenticar sobre ese mismo recurso , no en ningún otro lado.

En realidad, RESTfulness solo se aplica a RECURSOS, como lo indica un Identificador Universal de Recursos. Por lo tanto, incluso hablar de encabezados, cookies, etc., con respecto a REST no es realmente apropiado. REST puede funcionar sobre cualquier protocolo, aunque rutinariamente se realice a través de HTTP.

El principal determinante es este: si envía una llamada REST, que es un URI, una vez que la llamada llega al servidor con éxito, ese URI devuelve el mismo contenido, suponiendo que no se hayan realizado las transiciones (PUT, POST, DELETE) ? Esta prueba excluiría errores o solicitudes de autenticación devueltas, porque en ese caso, la solicitud aún no ha llegado al servidor, es decir, el servlet o la aplicación que devolverá el documento correspondiente al URI dado.

Del mismo modo, en el caso de un POST o PUT, ¿puede enviar un URI / carga útil determinada e independientemente de cuántas veces envíe el mensaje, siempre actualizará los mismos datos, de modo que los GET subsiguientes arrojen un resultado consistente?

REST tiene que ver con los datos de la aplicación, no con la información de bajo nivel requerida para transferir esos datos.

En la siguiente publicación del blog, Roy Fielding dio un buen resumen de toda la idea de REST:

http://groups.yahoo.com/neo/groups/rest-discuss/conversations/topics/5841

“Un sistema RESTful progresa de un estado estable al siguiente, y cada estado estable es tanto un estado de inicio potencial como un estado final potencial. Es decir, un sistema RESTful es un número desconocido de componentes que obedecen a un conjunto simple de reglas tales que están siempre en REST o en transición de un estado RESTful a otro estado RESTful. Cada estado puede ser completamente entendido por la (s) representación (es) que contiene y el conjunto de transiciones que proporciona, con las transiciones limitadas a un uniforme conjunto de acciones para ser comprensible. El sistema puede ser un diagtwig de estado complejo, pero cada agente de usuario solo puede ver un estado a la vez (el estado estacionario actual) y, por lo tanto, cada estado es simple y puede analizarse independientemente. el usuario, OTOH, puede crear sus propias transiciones en cualquier momento (por ejemplo, ingresar una URL, seleccionar un marcador, abrir un editor, etc.) “.


Yendo al tema de la autenticación, ya sea que se realice a través de cookies o encabezados, siempre que la información no sea parte de la carga URI y POST, realmente no tiene nada que ver con REST. Por lo tanto, en lo que respecta a ser apátrida, estamos hablando solo de los datos de la aplicación.

Por ejemplo, cuando el usuario ingresa datos en una pantalla de GUI, el cliente realiza un seguimiento de los campos que se han ingresado, los que no tienen, los campos obligatorios que faltan, etc. Este es todo el CONTEXTO DEL CLIENTE, y no se debe enviar ni rastrear por el servidor. Lo que se envía al servidor es el conjunto completo de campos que se deben modificar en el recurso IDENTIFICADO (por el URI), de modo que se produce una transición en ese recurso de un estado RESTful a otro.

Por lo tanto, el cliente realiza un seguimiento de lo que está haciendo el usuario y solo envía lógicamente transiciones de estado completas al servidor.

La transacción HTTP, autenticación de acceso básico, no es adecuada para RBAC, porque la autenticación de acceso básico utiliza el nombre de usuario cifrado: contraseña cada vez para identificar, mientras que lo que se necesita en RBAC es el Rol que el usuario quiere usar para una llamada específica. RBAC no valida los permisos en el nombre de usuario, sino en los roles.

Podría hacer un tric para concatenar de esta manera: usernameRole: password, pero esta es una mala práctica, y también ineficiente porque cuando un usuario tiene más roles, el motor de autenticación debería probar todos los roles en concatenación, y cada llamada nuevamente. Esto destruiría una de las mayores ventajas técnicas de RBAC, es decir, una prueba de autorización muy rápida.

Entonces ese problema no se puede resolver usando la autenticación de acceso básico.

Para resolver este problema, el mantenimiento de la sesión es necesario, y eso parece, de acuerdo con algunas respuestas, en contradicción con REST.

Eso es lo que me gusta de la respuesta de que REST no debe tratarse como una religión. En casos comerciales complejos, en el cuidado de la salud, por ejemplo, RBAC es absolutamente común y necesario. Y sería una lástima si no se les permitiera usar REST porque todos los diseñadores de herramientas REST tratarían a REST como una religión.

Para mí, no hay muchas maneras de mantener una sesión a través de HTTP. Uno puede usar cookies, con un sessionId, o un encabezado con un sessionId.

Si alguien tiene otra idea, me complacerá escucharla.

  1. Las sesiones no son RESTless
  2. ¿Quiere decir que el servicio REST solo se usa para http o me equivoqué? La sesión basada en cookies debe usarse solo para servicios propios (!) Basados ​​en http. (Podría ser un problema trabajar con cookies, p. Ej., Desde Mobile / Console / Desktop / etc.)
  3. si proporciona un servicio RESTful para desarrolladores de fiestas en 3D, nunca use sesiones basadas en cookies, use tokens para evitar los problemas de seguridad.