¿Puedes ayudarme a entender esto? "Errores comunes de REST: las sesiones son irrelevantes"

159

Descargo de responsabilidad: soy nuevo en la escuela de pensamiento REST, y estoy tratando de entenderlo.

Entonces, estoy leyendo esta página, Errores comunes de REST , y he descubierto que estoy completamente desconcertado porque la sección sobre sesiones es irrelevante. Esto es lo que dice la página:

No debería ser necesario que un cliente "inicie sesión" o "inicie una conexión". La autenticación HTTP se realiza automáticamente en cada mensaje. Las aplicaciones del cliente son consumidores de recursos, no servicios. Por lo tanto, no hay nada para iniciar sesión. Supongamos que está reservando un vuelo en un servicio web REST. No crea una nueva conexión de "sesión" al servicio. En su lugar, le pide al "objeto creador del itinerario" que le cree un nuevo itinerario. Puede comenzar a completar los espacios en blanco, pero luego obtener un componente totalmente diferente en otra parte de la web para completar algunos otros espacios en blanco. No hay sesión, por lo que no hay problema de migrar el estado de la sesión entre clientes. Tampoco hay problema de "afinidad de sesión"

De acuerdo, entiendo que la autenticación HTTP se realiza automáticamente en cada mensaje, pero ¿cómo? ¿Se envía el nombre de usuario / contraseña con cada solicitud? ¿Eso no solo aumenta el área de superficie de ataque? Siento que me falta parte del rompecabezas.

Sería malo tener un servicio REST, por ejemplo, /sessionque acepte una solicitud GET, donde pasaría un nombre de usuario / contraseña como parte de la solicitud, y devuelva un token de sesión si la autenticación fue exitosa, eso podría ser entonces pasó junto con las solicitudes posteriores? ¿Tiene sentido desde el punto de vista REST, o es que falta el punto?

Robar
fuente
cada solicitud siempre se autentica, el secuestro de sesión es una cosa. el descanso hace que esto sea más obvio pero no más expuesto.
Jasen

Respuestas:

79

Para ser RESTful, cada solicitud HTTP debe llevar suficiente información por sí misma para que su destinatario la procese para estar en completa armonía con la naturaleza sin estado de HTTP.

De acuerdo, entiendo que la autenticación HTTP se realiza automáticamente en cada mensaje, pero ¿cómo?

Sí, el nombre de usuario y la contraseña se envían con cada solicitud. Los métodos comunes para hacerlo son la autenticación de acceso básica y la autenticación de acceso de resumen . Y sí, un espía puede capturar las credenciales del usuario. Por lo tanto, uno cifraría todos los datos enviados y recibidos utilizando Transport Layer Security (TLS) .

¿Sería malo tener un servicio REST, por ejemplo, / sesión, que acepte una solicitud GET, donde pasaría un nombre de usuario / contraseña como parte de la solicitud, y devuelva un token de sesión si la autenticación fue exitosa, eso podría luego se pasa junto con las solicitudes posteriores? ¿Tiene sentido desde el punto de vista REST, o es que falta el punto?

Esto no sería RESTful ya que tiene un estado, pero es bastante común, ya que es una conveniencia para los usuarios; un usuario no tiene que iniciar sesión cada vez.

Lo que describe en un "token de sesión" se conoce comúnmente como cookie de inicio de sesión . Por ejemplo, si intentas iniciar sesión en tu Yahoo! cuenta hay una casilla de verificación que dice "mantenerme conectado durante 2 semanas". Esto es esencialmente decir (en sus palabras) "mantenga vivo mi token de sesión durante 2 semanas si inicio sesión correctamente". Los navegadores web enviarán dichas cookies de inicio de sesión (y posiblemente otras) con cada solicitud HTTP que usted le solicite.

z8000
fuente
55
Esta respuesta no tiene sentido para mí. Primero, dice que está bien pasar el nombre de usuario y la contraseña cada vez y, por lo tanto, también una vez, lo cual tiene sentido. Luego, se sugiere la idea de devolver al cliente el estado de inicio de sesión exitoso en forma de token. Si es necesario, el token podría codificar el tiempo de creación. Ciertamente se nos permite devolver información al cliente. Entonces, esta sugerencia me parece bien. La respuesta dice que no está bien porque "lleva estado", pero ¿no es la idea de "ST" en "REST" que ese estado se puede transferir entre el cliente y el servidor?
33

No es raro que un servicio REST requiera autenticación para cada solicitud HTTP. Por ejemplo, Amazon S3 requiere que cada solicitud tenga una firma derivada de las credenciales del usuario, la solicitud exacta que se debe realizar y la hora actual. Esta firma es fácil de calcular en el lado del cliente, puede ser verificada rápidamente por el servidor y es de uso limitado para un atacante que la intercepta (ya que se basa en la hora actual).

Greg Hewgill
fuente
3
+1, ¿puede dar más detalles sobre: es de uso limitado para un atacante que lo intercepta (ya que se basa en la hora actual) ? ¿No estás hablando de una cookie que contiene nombre de usuario y contraseña cifrados? como lo hace SO? (En mi humilde opinión)
Royi Namir
2
@RoyiNamir: No estoy hablando de una cookie. La firma utilizada por S3 es un parámetro para la solicitud HTTP, pero no es una cookie, se recalcula para cada solicitud.
Greg Hewgill
Entonces, si necesito guardar información sobre un usuario, ¿dónde la guardaría? en db? No quiero ir a cada solicitud a db ... y todavía quiero usar el descanso ... ¿pueden ayudarme?
Royi Namir
@RoyiNamir: Si tiene preguntas específicas sobre cómo lograr algún objetivo, haga una nueva pregunta . No puedo responder preguntas adicionales aquí en los comentarios.
Greg Hewgill
10

Muchas personas no entienden los principales REST muy claramente, el uso de un token de sesión no significa que siempre tenga estado, la razón para enviar un nombre de usuario / contraseña con cada solicitud es solo para la autenticación y lo mismo para enviar un token (generado por inicio de sesión proceso) solo para decidir si el cliente tiene permiso para solicitar datos o no, ¡solo viola las convenciones REST cuando usa un nombre de usuario / contraseña o tokens de sesión para decidir qué datos mostrar! en su lugar, debe usarlos solo para la autenticación (para mostrar datos o no)

en su caso, digo SÍ, esto es RESTy, ¡pero trate de evitar el uso de sesiones php nativas en su API REST y comience a generar sus propios tokens hash que caducan en un período de tiempo determinado!

EvilThinker
fuente
1
gracias. ¿Por qué debería uno evitar la sesión php nativa y usar tokens hash propios?
Matthew
No es una razón brillante, digo, solo por más seguridad y más control.
EvilThinker
Esto es mejor que la respuesta aceptada. Por lo menos, acepta la sugerencia como RESTy, lo cual tiene sentido. Sin embargo, no veo por qué la información pasada no se puede utilizar para hacer una autorización dependiente del usuario. Algunos usuarios pueden tener acceso a algunos datos y otros no. Eso no hace que el protocolo no sea RESTful.
8

No, no se pierde el punto. ClientLogin de Google funciona exactamente de esta manera con la notable excepción de que se le indica al cliente que vaya a la "/ sesión" utilizando una respuesta HTTP 401. Pero esto no crea una sesión, solo crea una forma para que los clientes se autentiquen (temporalmente) sin pasar las credenciales de forma clara, y para que el servidor controle la validez de estas credenciales temporales como mejor le parezca.

mogsie
fuente
11
@ unforgiven3 Mientras el token devuelto solo se use para autenticar al usuario y no lo use el servidor para asociar al usuario a otro estado almacenado en el servidor, entonces no veo que se violen las restricciones REST.
Darrel Miller
44
@ unforgiven3 El token devuelto por el servidor es, en efecto, una prueba de que el usuario es quien dice ser. Por lo tanto, en lugar de cada solicitud, incluido el nombre de usuario y la contraseña, cada solicitud incluye el token que está construido de tal manera que el servidor pueda confiar en su veracidad.
Darrel Miller
1
@ inolvidable3, Darrel tiene razón. El token repetido tendría que ser enviado por el cliente en cada solicitud HTTP, al igual que en la autenticación de resumen básica, hasta que el token caduque. Cuando eso sucede, el cliente puede repetir el inicio de sesión y, opcionalmente, solicitar credenciales al usuario, o lo que sea. Podría elaborar la respuesta, si quieres. editar: (¡Y gracias por mantenerse al día con las respuestas a viejas preguntas!)
mogsie
1
No hay problema, mogsie, siempre es interesante discutir este tipo de cosas :-) Creo que veo a dónde están yendo con esto, desafortunadamente no entiendo lo suficiente sobre la autenticación de resumen para comprender realmente esto (principalmente, simplemente no entiendo entiendo cómo se devuelve el token a cada solicitud HTTP, pero eso parece ser un detalle de implementación). Sin embargo, ahora veo por qué este método no viola los principios REST. Gracias por las respuestas!
Rob
66
@ unforgiven3, esto puede ayudar: el token es una pieza de información firmada. Entonces es autónomo. El servidor puede validar el token sin verificar un estado almacenado previamente. Por lo tanto, es solo un estado que se almacena en el cliente y se transfiere de un lado a otro.
Iravanchi
5

De acuerdo, entiendo que la autenticación HTTP se realiza automáticamente en cada mensaje, pero ¿cómo?

"Autorización:" encabezado HTTP enviado por el cliente. Ya sea básico (texto sin formato) o resumen.

¿Sería malo tener un servicio REST, por ejemplo, / sesión, que acepte una solicitud GET, donde pasaría un nombre de usuario / contraseña como parte de la solicitud, y devuelva un token de sesión si la autenticación fue exitosa, eso podría luego se pasa junto con las solicitudes posteriores? ¿Tiene sentido desde el punto de vista REST, o es que falta el punto?

La idea de la sesión es hacer con estado aplicaciones que utilizan el protocolo sin estado (HTTP) y el cliente mudo (navegador web), por el mantenimiento del estado del lado del servidor. Uno de los principios de REST es "Cada recurso es direccionable de manera única utilizando una sintaxis universal para usar en enlaces hipermedia" . Las variables de sesión son algo a lo que no se puede acceder a través de URI. La aplicación verdaderamente RESTful mantendría el estado del lado del cliente, enviando todas las variables necesarias por HTTP, preferiblemente en el URI.

Ejemplo: búsqueda con paginación. Tendrías URL en forma

http://server/search/urlencoded-search-terms/page_num

Tiene mucho en común con las URL marcables

vartec
fuente
44
Sin embargo, tampoco se puede acceder a la información de autenticación a través de URI: todos hablan de enviar información de autenticación como parte del encabezado de la solicitud. ¿En qué se diferencia eso de incluir un token de sesión con la solicitud? No digo que use el token de sesión en el URI, sino en los datos pasados ​​en la solicitud.
Rob
La autenticación establece si está autorizado para ejecutar esa acción, y en la aplicación RESTful no afectaría su resultado.
vartec
44
Un token de sesión también establece si estás autorizado para ejecutar esa acción. ¿Qué quieres decir con que no afectaría su resultado? Si la persona que llama no está autorizada, recibirá un error No autorizado. Lo mismo con un token de sesión. ¿Realmente no veo la diferencia?
Rob
3
No, el token de sesión es un identificador del estado guardado en el servidor. Eso simplemente no es RESTful. En cuanto a No autorizado, no lo veo como resultado. Prefiero considerar eso una excepción (como en try / catch).
vartec
Muy bien, vartec, eso tiene sentido. ¡Gracias por el seguimiento!
Rob
3

Creo que su sugerencia está bien, si desea controlar el tiempo de vida de la sesión del cliente. Creo que la arquitectura RESTful lo alienta a desarrollar aplicaciones sin estado. Como @ 2pence escribió "cada solicitud HTTP debe llevar suficiente información por sí misma para que su destinatario la procese para estar en completa armonía con la naturaleza sin estado de HTTP" .

Sin embargo, no siempre es así, a veces la aplicación necesita saber cuándo el cliente inicia o cierra sesión y debe mantener recursos como bloqueos o licencias basados ​​en esta información. Vea mi pregunta de seguimiento para un ejemplo de tal caso.

LiorH
fuente