una sirve servicios servicio restful qué para entre ejemplo diferencia arquitectura web-services authentication rest restful-authentication client-certificates

web-services - sirve - servicios web rest



Servicio web RESTful: ¿cómo autenticar las solicitudes de otros servicios? (9)

Estoy diseñando un servicio web RESTful al que deben acceder los usuarios, pero también otros servicios web y aplicaciones. Todas las solicitudes entrantes necesitan ser autenticadas. Toda la comunicación tiene lugar a través de HTTPS. La autenticación de usuario va a funcionar en función de un token de autenticación, adquirido mediante la colocación del nombre de usuario y la contraseña (a través de una conexión SSL) a un recurso / sesión provisto por el servicio.

En el caso de los clientes del servicio web, no hay un usuario final detrás del servicio al cliente. Las solicitudes se inician mediante tareas programadas, eventos u otras operaciones informáticas. La lista de servicios de conexión se conoce de antemano (obviamente, supongo). ¿Cómo debo autenticar estas solicitudes provenientes de otros servicios (web)? Quiero que el proceso de autenticación sea lo más fácil posible para implementar esos servicios, pero no a costa de la seguridad. ¿Cuál sería el estándar y las mejores prácticas para un escenario como este?

Opciones que puedo pensar (o me han sugerido):

  1. Haga que los servicios del cliente recurran a tener un nombre de usuario y una contraseña "falsos" y autentíquelos de la misma manera que a los usuarios. No me gusta esta opción, simplemente no me parece bien.

  2. Asigne un ID de aplicación permanente para el servicio al cliente, posiblemente una clave de aplicación también. Por lo que he entendido, esto es lo mismo que tener nombre de usuario + contraseña. Con esta identificación y clave, puedo autenticar cada solicitud o crear un token de autenticación para autenticar más solicitudes. De cualquier manera, no me gusta esta opción, porque cualquiera que pueda obtener la identificación y la clave de la aplicación puede hacerse pasar por el cliente.

  3. Podría agregar una verificación de dirección IP a la opción anterior. Esto haría más difícil realizar solicitudes falsas.

  4. Certificados de cliente Configurar mi propia autoridad de certificación, crear certificado raíz y crear certificados de cliente para los servicios del cliente. Sin embargo, me vienen a la mente un par de cuestiones: a) ¿cómo puedo permitir que los usuarios se autentiquen sin certificados yb) qué tan complicado es implementar este escenario desde el punto de vista del servicio al cliente?

  5. Algo más: debe haber otras soluciones por ahí.

Mi servicio se ejecutará en Java, pero deliberadamente omití información sobre el marco específico en el que se construiría, porque estoy más interesado en los principios básicos y no tanto en los detalles de implementación. Supongo que la mejor solución para esto será ser posible implementar independientemente del marco subyacente. Sin embargo, soy un poco inexperto con este tema, por lo que los consejos concretos y ejemplos sobre la implementación real (como bibliotecas útiles de terceros, artículos, etc.) serán muy apreciados también.


Además de la autenticación, te sugiero que pienses en el panorama general. Considere hacer su servicio RESTful back-end sin ninguna autenticación; a continuación, coloque una autenticación muy simple que requiere el servicio de capa intermedia entre el usuario final y el servicio de back-end.


Cualquier solución a este problema se reduce a un secreto compartido. Tampoco me gusta la opción de nombre de usuario y contraseña codificadas, pero tiene el beneficio de ser bastante simple. El certificado del cliente también es bueno, pero ¿es realmente muy diferente? Hay un certificado en el servidor y otro en el cliente. Su principal ventaja es que es más difícil que la fuerza bruta. Sin embargo, afortunadamente tiene otras protecciones para proteger contra eso.

No creo que su punto A para la solución de certificado de cliente sea difícil de resolver. Usted solo usa una rama. if (client side certificat) { check it } else { http basic auth } No soy un experto en Java y nunca he trabajado con él para hacer certificados del lado del cliente. Sin embargo, un rápido Google nos lleva a este tutorial que se ve en tu callejón.

A pesar de todo este debate sobre "lo mejor", permítanme señalar que existe otra filosofía que dice: "menos código, menos inteligencia es mejor". (Yo personalmente tengo esta filosofía). La solución de certificado del cliente suena como un montón de código.

Sé que usted expresó preguntas sobre OAuth, pero la propuesta de OAuth2 incluye una solución a su problema llamada " tokens de portador " que debe usarse junto con SSL. Creo que, en aras de la simplicidad, elegiría el usuario / pase codificado (uno por aplicación para que puedan ser revocados individualmente) o los tokens de portador muy similares.


Después de leer su pregunta, diría que generar un token especial para hacer la solicitud requerida. Este token vivirá en un tiempo específico (digamos en un día).

Aquí hay un ejemplo de para generar token de autenticación:

(day * 10) + (month * 100) + (year (last 2 digits) * 1000)

por ejemplo: 3 de junio de 2011

(3 * 10) + (6 * 100) + (11 * 1000) = 30 + 600 + 11000 = 11630

luego concatenar con la contraseña del usuario, ejemplo "my4wesomeP4ssword!"

11630my4wesomeP4ssword!

Luego haz MD5 de esa cadena:

05a9d022d621b64096160683f3afe804

Cuando llamas a una solicitud, usa siempre esta ficha,

https://mywebservice.com/?token=05a9d022d621b64096160683f3afe804&op=getdata

Este token siempre es único cada día, así que supongo que este tipo de protección es más que suficiente para proteger siempre tu servicio.

Hope ayuda

:)


En lo que respecta al enfoque del certificado del cliente, no sería terriblemente difícil implementarlo al mismo tiempo que permite el acceso a los usuarios sin certificados de cliente.

Si de hecho creó su propia Autoridad de certificación autofirmada y emitió certificados de cliente para cada servicio de cliente, tendría una manera fácil de autenticar esos servicios.

Dependiendo del servidor web que esté utilizando, debe haber un método para especificar la autenticación del cliente que aceptará un certificado del cliente, pero no requiere uno. Por ejemplo, en Tomcat al especificar su conector https, puede establecer ''clientAuth = want'', en lugar de ''true'' o ''false''. Luego, asegúrese de agregar su certificado CA autofirmado a su almacén de confianza (de forma predeterminada, el archivo cacerts en el JRE que está utilizando, a menos que haya especificado otro archivo en la configuración de su servidor web), por lo que los únicos certificados confiables serían los emitidos fuera de tu CA auto-firmado

Del lado del servidor, solo permitiría el acceso a los servicios que desea proteger si puede recuperar un certificado de cliente de la solicitud (no nulo) y pasa las comprobaciones de DN si prefiere alguna seguridad adicional. Para los usuarios sin certificaciones de clientes, aún podrían acceder a sus servicios, pero simplemente no tendrán certificados presentes en la solicitud.

En mi opinión, esta es la forma más ''segura'', pero sin duda tiene su curva de aprendizaje y gastos generales, por lo que puede no ser necesariamente la mejor solución para sus necesidades.


Hay varios enfoques diferentes que puede tomar.

  1. Los puristas RESTful querrán que use la autenticación BASIC y envíe credenciales en cada solicitud. Su razón de ser es que nadie está almacenando ningún estado.

  2. El servicio al cliente podría almacenar una cookie, que mantiene una ID de sesión. Personalmente, no considero esto ofensivo como algunos de los puristas que conozco; puede ser costoso autenticarse una y otra vez. Aunque parece que no te gusta esta idea.

  3. Según tu descripción, realmente parece que podrías estar interesado en OAuth2 Mi experiencia hasta el momento, por lo que he visto, es que es un poco confusa y un poco agotadora. Hay implementaciones, pero son pocas y distantes. En Java, entiendo que se ha integrado en los módulos de security de Spring3. (Su tutorial está muy bien escrito.) He estado esperando para ver si habrá una extensión en Restlet , pero hasta ahora, aunque se ha propuesto, y puede estar en la incubadora, todavía no se ha incorporado por completo.


Puede crear Session en el servidor y compartir sessionId entre el cliente y el servidor con cada llamada REST.

  1. Primero autentique la solicitud REST: /authenticate . Respuesta de devolución (según el formato de su cliente) con sessionId: ABCDXXXXXXXXXXXXXX ;

  2. Almacene esta sessionId de sessionId en el Map con la sesión real. Map.put(sessionid, session) o use SessionListener para crear y destruir claves para usted;

    public void sessionCreated(HttpSessionEvent arg0) { // add session to a static Map } public void sessionDestroyed(HttpSessionEvent arg0) { // Remove session from static map }

  3. Obtenga sessionid con cada llamada REST, como URL?jsessionid=ABCDXXXXXXXXXXXXXX (o de otra manera);

  4. HttpSession del mapa usando sessionId ;
  5. Valide la solicitud para esa sesión si la sesión está activa;
  6. Enviar respuesta o mensaje de error.

Utilizaría una aplicación para redirigir a un usuario a su sitio con un parámetro de id. De aplicación, una vez que el usuario apruebe la solicitud, generará un token único que la otra aplicación utilizará para la autenticación. De esta forma, las otras aplicaciones no manejan las credenciales del usuario y los usuarios pueden agregar, eliminar y administrar otras aplicaciones. Foursquare y algunos otros sitios se autentican de esta manera y es muy fácil de implementar como la otra aplicación.


Yo creo que el enfoque:

  1. Primera solicitud, el cliente envía el id / código de acceso
  2. Identificación de Exchange / pase para token único
  3. Validar ficha en cada solicitud posterior hasta que caduque

es bastante estándar, independientemente de cómo implemente y otros detalles técnicos específicos.

Si realmente desea empujar el sobre, quizás podría considerar la clave https del cliente en un estado inválido temporalmente hasta que se validen las credenciales, limitar la información si es que nunca lo son y otorgar acceso cuando se validan, basadas nuevamente en la caducidad.

Espero que esto ayude


5. Algo más: debe haber otras soluciones por ahí.

¡Tienes razón, hay! Y se llama JWT (JSON Web Tokens).

JSON Web Token (JWT) es un estándar abierto (RFC 7519) que define una forma compacta y autónoma para transmitir de forma segura información entre las partes como un objeto JSON. Esta información puede ser verificada y confiable porque está firmada digitalmente. Los JWT se pueden firmar usando un secreto (con el algoritmo HMAC) o un par de claves públicas / privadas usando RSA.

Recomiendo investigar JWT. Son una solución mucho más simple al problema cuando se compara con soluciones alternativas.

https://jwt.io/introduction/