2008-10-29 8 views
65

Estoy comenzando a construir una API REST para un proyecto en el que estoy trabajando, y esto me llevó a investigar un poco sobre la mejor manera de construir una API usando RoR. Descubrí muy rápidamente que, de forma predeterminada, los modelos están abiertos al mundo y se pueden llamar a través de URL simplemente colocando un ".xml" al final de la URL y pasando los parámetros apropiados.Buscando sugerencias para construir una API REST segura dentro de Ruby on Rails

Entonces llegó la siguiente pregunta. ¿Cómo aseguro mi aplicación para evitar cambios no autorizados? Al hacer algunas investigaciones, encontré un par de artículos que hablan sobre attr_accessible y attr_protected y cómo se pueden usar. La URL específica que encontré hablando de estos se publicó en mayo de 2007 (here).

Como con todas las cosas ruby, estoy seguro de que las cosas han evolucionado desde entonces. Entonces mi pregunta es, ¿sigue siendo esta la mejor manera de asegurar una API REST dentro de RoR?

Si no, ¿qué sugiere en un escenario de "proyecto nuevo" o de "proyecto existente"?

+0

Si el cliente sabe cómo manipular sus URI (al agregar .xml o de otro modo), entonces su API no es REST. – aehlke

+0

esta es una buena biblioteca de Servidor Oauth 2.0 para ruby ​​https://github.com/Lelylan/rest-oauth2-server – sparkle

Respuesta

100

Existen varios esquemas para autenticar solicitudes de API, y son diferentes a la autenticación normal proporcionada por complementos como restful_authentication o acts_as_authenticated. Lo más importante es que los clientes no mantendrán sesiones, por lo que no existe el concepto de inicio de sesión.

autenticación HTTP

Puede utilizar la autenticación básica HTTP. Para esto, los clientes API utilizará un nombre de usuario y contraseña regular y sólo hay que poner en la URL de esta manera:

http://myusername:[email protected]/ 

Creo que restful_authentication apoya esta fuera de la caja, por lo que puede pasar por alto si alguien está usando su aplicación a través de la API o a través de un navegador.

Una desventaja aquí es que les pides a los usuarios que pongan su nombre de usuario y contraseña a la vista en cada solicitud. Al hacerlo a través de SSL, puede hacer esto seguro.

Creo que nunca he visto una API que lo use. A mí me parece una buena idea, sobre todo porque los esquemas de autenticación actuales lo admiten de manera inmediata, así que no sé cuál es el problema.

clave de API

Otra manera fácil de activar la autenticación de la API es el uso de claves de la API. Básicamente es un nombre de usuario para un servicio remoto. Cuando alguien se registra para usar su API, les da una clave API. Esto debe pasar con cada solicitud.

Un inconveniente aquí es que si alguien obtiene la clave de API de otra persona, puede realizar solicitudes como ese usuario. Creo que haciendo que todas sus solicitudes de API utilicen HTTPS (SSL), puede compensar este riesgo de alguna manera.

Otro inconveniente es que los usuarios usan las mismas credenciales de autenticación (la clave de API) donde quiera que vayan. Si quieren revocar el acceso a un cliente API, su única opción es cambiar su clave API, lo que deshabilitará también a todos los demás clientes. Esto puede mitigarse permitiendo a los usuarios generar múltiples claves API.

clave de API + firma clave secreta

Desaprobado (tipo de) - ver abajo OAuth

Significativamente más compleja es la firma de la solicitud con una clave secreta. Esto es lo que Amazon Web Services (S3, EC2 y demás). Esencialmente, le das al usuario 2 claves: su clave API (es decir, nombre de usuario) y su clave secreta (es decir, contraseña). La clave API se transmite con cada solicitud, pero la clave secreta no. En su lugar, se usa para firmar cada solicitud, generalmente agregando otro parámetro.

IIRC, Amazon lo logra tomando todos los parámetros de la solicitud y ordenándolos por nombre de parámetro. Luego, esta cadena se somete a hash, usando la clave secreta del usuario como la tecla de almohadilla. Este nuevo valor se agrega como un nuevo parámetro a la solicitud antes de ser enviado. Por parte de Amazon, hacen lo mismo. Toman todos los parámetros (excepto la firma), los piden y hash usando la clave secreta. Si esto coincide con la firma, saben que la solicitud es legítima.

El inconveniente aquí es la complejidad. Conseguir que este esquema funcione correctamente es un problema, tanto para el desarrollador de API como para los clientes. Espere muchas llamadas de soporte y correos electrónicos molestos de desarrolladores de clientes que no pueden hacer que las cosas funcionen.

OAuth

Para combatir algunos de los problemas de complejidad con la tecla + firma secreta, un estándar ha surgido llamado OAuth. En el núcleo OAuth es un sabor de clave + firma secreta, pero gran parte está estandarizado y se ha incluido en libraries for many languages.

En general, es mucho más fácil tanto para el productor de API como para el consumidor utilizar OAuth en lugar de crear su propio sistema de clave/firma.

OAuth también segmenta el acceso inherentemente, proporcionando diferentes credenciales de acceso para cada consumidor API. Esto permite a los usuarios revocar selectivamente el acceso sin afectar sus otras aplicaciones consumidoras.

Específicamente para Ruby, hay un OAuth gem que proporciona asistencia inmediata para los productores y consumidores de OAuth. He usado esta joya para construir una API y también para consumir API OAuth y quedé muy impresionado. Si crees que tu aplicación necesita OAuth (a diferencia del esquema de clave API más simple), entonces puedo recomendar fácilmente el uso de la gema OAuth.

+0

Muchas personas van por la clave API + ruta de firma, ¿alguien sabe si hay una "mejor manera"? ! – MatthewFord

+0

Una buena respuesta - esto finalmente lo aclaró para mí con los diferentes niveles. ¡Gracias! –

+2

Hay dos grandes problemas con HTTP "Autorización:". El primero es que el servidor decide sobre el esquema de autenticación, lo que significa que la autenticación implícita no evita el compromiso de contraseñas por parte de un MITM (solo pretende que solo admite Basic). El segundo es que la autenticación básica no está limitada a una ruta, por lo que cualquier persona en un servidor web compartido puede obtener la contraseña de otra persona (muchas personas cambian a subdominios por este motivo, junto con las cookies y la configuración de Apache en general más sana). –

3

Me enfrento a preguntas similares a las de usted en este momento porque también estoy construyendo una APLICACIÓN REST para una aplicación de rieles.

Sugiero asegurarme de que solo los atributos que pueden ser editados por el usuario estén marcados con attr_accessible. Esto configurará una lista blanca de atributos que se pueden asignar usando atributos_actualización.

Lo que hago es algo como esto:

class Model < ActiveRecord::Base 
     attr_accessible nil 
    end 

Todos mis modelos heredan de que, por lo que se ven obligados a definir attr_accessible para cualquier campo que quieren hacer masa asignable. Personalmente, me gustaría que hubiera una forma de habilitar este comportamiento por defecto (puede haber, y no lo sé).

Para que sepas, alguien puede asignar en masa una propiedad no solo usando la API REST sino también usando una publicación regular.

7

¿Cómo puedo proteger mi aplicación para evitar cambios no autorizados?

attr_accessible y attr_protected son ambos útiles para controlar la capacidad de realizar los medios de asignaciones en un modelo ActiveRecord. Definitivamente desea usar attr_protected para evitar ataques de inyección de formularios; ver Use attr_protected or we will hack you.

Además, para evitar que alguien pueda acceder a los controladores en su aplicación Rails, es casi seguro que va a necesitar algún tipo de sistema de autenticación de usuario y poner un before_filter en sus controladores para asegurarse de tener una usuario autorizado que realiza la solicitud antes de permitir que se ejecute la acción solicitada del controlador.

Consulte el Ruby on Rails Security Guide (parte del Proyecto de documentación de Rails) para obtener más información útil.

0

Otro enfoque que ahorra la construcción de muchas de las cosas es usar algo como http://www.3scale.net/ que maneja claves, tokens, cuotas, etc. para desarrolladores individuales. También realiza análisis y crea un portal para desarrolladores.

Hay un plugin ruby ​​/ rails ruby API plugin que se aplicará a las políticas para el tráfico tal como llega - se puede usar junto con el oAuth gem. También puede hacerlo soltando barniz delante de la aplicación y usando la modificación de barn mod: Varnish API Module.