2009-01-19 31 views
67

Actualmente estoy trabajando en una biblioteca REST para .net, y me gustaría escuchar algunas opiniones sobre un punto abierto que tengo: REST y autenticación.REST y variantes de autenticación

Aquí es un ejemplo de una interfaz REST se utiliza con la biblioteca:

[RestRoot("/user")] 
public interface IUserInterface 
{ 
    [RestPut("/")] 
    void Add(User user); 

    [RestGet("/")] 
    int[] List(); 

    [RestGet("/get/{id}")] 
    User Get(int id); 

    [RestDelete("/delete/{id}")] 
    void Delete(int id); 
} 

El código del servidor a continuación, sólo implementa la interfaz y los clientes pueden obtener la misma interfaz a través de una fábrica. O si el cliente no está usando la biblioteca, una solicitud HTTP estándar también funciona.

Sé que existen las principales formas de utilizar HTTP Basic Auth o enviar un token a las solicitudes que requieren usuarios autenticados.

El primer método (autenticación básica de HTTP), tiene las siguientes cuestiones (en parte navegador web específico):

  • La contraseña se transmite con cada petición - incluso con SSL esto tiene algún tipo de "mal rollo" .
  • Dado que la contraseña se transmite con un encabezado de solicitud, sería fácil para un atacante local mirar los encabezados transmitidos para obtener la contraseña.
  • La contraseña está disponible en la memoria de los navegadores.
  • No hay forma estándar de caducar "sesiones" de usuario.
  • Iniciar sesión con un navegador interrumpe la apariencia de una página.

Los temas para el segundo método se centran más en la implementación y uso de la biblioteca:

  • Cada petición URI que necesita la autenticación debe tener un parámetro de la señal, la cual es muy repetitivo.
  • Hay mucho más código por escribir si cada implementación de método necesita verificar si un token es válido.
  • La interfaz será menos específica, p. [RestGet("/get/{id}")] contra [RestGet("/get/{id}/{token}")].
  • Dónde colocar el token: al final del URI? después de la raíz? ¿en algún otro lugar?

Mi idea era pasar el token como parámetro a la URL como http:/server/user/get/1234?token=token_id.

Otra posibilidad sería enviar el parámetro como un encabezado HTTP, pero supongo que complicaría el uso con clientes HTTP simples.

El token se volvería a pasar al cliente como un encabezado HTTP personalizado ("X-Session-Id") en cada solicitud.

Esto podría ser completamente abstraído de la interfaz, y cualquier implementación que necesite autenticación podría simplemente preguntar a qué usuario pertenece el token (si se le dio).

¿Crees que esto violaría demasiado el REST o ¿tienes alguna idea mejor?

Respuesta

63

Tiendo a creer que los detalles de autenticación pertenecen al encabezado, no al URI. Si confía en que se colocará un token en el URI, será necesario codificar cada URI de su aplicación para incluir el token. También afectaría negativamente el almacenamiento en caché. Los recursos con un token que cambia constantemente ya no podrán almacenarse en caché. La información relacionada con el recurso pertenece al URI, no a los datos relacionados con la aplicación, como las credenciales.

Parece que debe tener como objetivo los navegadores web como cliente? De ser así, podría investigar usando HTTP Digest access authentication o emitir a los clientes sus propios certificados SSL para identificarlos y autenticarlos de manera única. Además, no creo que las cookies de sesión sean necesariamente malas. Especialmente cuando tienes que lidiar con un navegador. Siempre que aisle el código de manejo de las cookies y haga que el resto de la aplicación no dependa de él, estaría bien. La clave es solo almacenar la identidad del usuario en la sesión, nada más. No abuse del estado de la sesión del servidor.

Si se dirige a clientes que no sean el navegador, existen varios enfoques que puede seguir. Tuve suerte al usar el mecanismo S3 Authentication de Amazon.

Esto es todo muy subjetivo, por supuesto. La pureza y seguir REST a la carta a veces puede ser poco práctico. Mientras minimices y aísles ese comportamiento, el núcleo de tu aplicación aún puede ser RESTful. Recomiendo encarecidamente RESTful Web Services como una gran fuente de información y enfoques de REST.

+2

Gracias por el enlace S3. – Fionn

+0

En el ejemplo S3, comparten claves criptográficas con clientes: esto es malo, ¿o no? –

+0

Como cualquier tipo de criptografía secreta compartida, es esencial que ambas partes mantengan el secreto de la clave. En ese sentido, no es peor que la criptografía simétrica. – laz

4

El resto de la autenticación que he visto trata las sesiones como un recurso REST para la creación, destrucción, etc. y luego la identificación de la sesión se pasa de un lado a otro.Los que he visto tienden a usar la cookie de sesión para esto, ya que es la única forma de protegerlo realmente. Si pasa la identificación de la sesión en la URL, no tiene ninguna forma de realmente autenticar que proviene del cliente correcto.

La autenticación es un problema complicado con REST, ya que requiere que se guarde alguna forma de estado fuera de la URL que infrinja los principios REST de la URL, ya que es todo lo que se necesita para representar el estado.

+0

Dado que siempre usará SSL si no se usa internamente en una red segura y el uso de UUID para las sesiones de dónde viene no debería ser un problema. ¿Y qué impide que alguien falsifique la cookie? – Fionn

+3

No diría que tener el URI sea todo lo que se requiere para representar el estado es un principio de REST. Por el contrario, tener recursos es direccionable y todo el estado de la aplicación que figura en la solicitud parece una mejor manera de expresarlo. – laz

+0

Aseguraría la cookie con un MAC, p. Ej.el servidor tiene un secreto y sería entregar al cliente la siguiente sesión-token: _ donde mac se construye como SHA1 ( _ ) Cuando un cliente envía una ficha _ el servidor debe compruebe si _ es igual a ordnungswidrig

16

Estoy de acuerdo con workmad3, si se necesita mantener el tiempo de vida de la sesión, debe crear un recurso de sesión. Publicar en ese recurso con credenciales de usuario (autenticación básica o credenciales en el contenido del cuerpo) devolverá una identificación de sesión única. Eliminar en/session/{id} cerrará la sesión del usuario.

Si desea controlar el tiempo de caducidad de la sesión. Al crear una nueva sesión (publicar en el recurso de la sesión), el servidor configurará una cookie en la respuesta (usando el encabezado de conjunto de cookies estándar). La cookie contendrá el tiempo de caducidad. La cadena de cookies se debe cifrar en el servidor, por lo que solo el servidor puede abrir esa cookie. Cada solicitud consiguiente al servidor enviará la cookie de sesión en el encabezado de la cookie. (se hará automáticamente si su cliente es un navegador). El servidor debe "renovar" la cookie para cada solicitud, es decir, crear una nueva cookie con un nuevo tiempo de caducidad (extender el tiempo de espera de la sesión). Recuerde borrar la cookie cuando el usuario llama a eliminar en el recurso de la sesión.

Si desea que su aplicación sea más segura, puede almacenar la IP del cliente en la misma cookie, de modo que cuando llegue una solicitud, el servidor puede validar que fue enviada desde el cliente "original". Pero recuerde que esta solución puede ser problemática cuando se trata de proxys, ya que el servidor podría "ver" todas las solicitudes como procedentes del mismo cliente.

+0

No veo un problema con los proxies aquí. Es solo que la seguridad adicional se reduce por el hecho de que algunos clientes parecen ser los mismos. Las cookies también deberían ser [httpOnly] (http://en.wikipedia.org/wiki/HTTP_cookie#HttpOnly_cookie). – maaartinus

Cuestiones relacionadas