Asegurar las contraseñas para la autenticación REST

3

Estoy desarrollando una aplicación REST utilizando Spring Framework, como parte de los requisitos, tenemos que asegurar las diferentes funciones del sistema a diferentes roles de usuario (cosas bastante estándar). Mi método actual para determinar los roles para el usuario que ha iniciado sesión actualmente es que cada vez que llaman a una URL REST desde el frontend, agrego una cadena codificada en Base 64 al encabezado de la solicitud. Esta cadena cuando se decodifica se resuelve con su nombre de usuario y un hash de contraseña generado por bCrypt en este formato nombre de usuario: hashedpassword.

Me preocupa un poco que esto no sea seguro, a pesar de que la solicitud se realizará a través de una conexión HTTP segura, ya que podría dar acceso a un posible pirata informático al menos al nombre de usuario de los usuarios. No pudieron obtener la contraseña porque eso es solo un valor hash, pero podrían usar ese valor hash para llamar a la API REST correctamente.

¿Cómo puedo asegurar este sistema correctamente? ¿Debo agregar un token de sesión o algún tipo de clave generada al azar para la sesión?

Mi pregunta de seguimiento es, entonces, ¿cómo puedo hacer esto RESTAMENTE? Estaba pensando que podría generar (usando bCrypt) un hash que representaba el nombre de usuario: hashpasspassword en el inicio de sesión, guardarlo en la base de datos y verificarlo cada vez que se realiza una llamada REST. Cuando el usuario cierre la sesión, simplemente configúrelo en nulo. Enjuague y repita. De esa manera, cualquier atacante potencial solo obtendría una única cadena de bCrypt que no expondría el nombre de usuario, pero aún podrían usar esa cadena para llamar a la API REST.

    
pregunta JamesENL 14.04.2014 - 09:19
fuente

2 respuestas

4

Los siguientes enlaces pueden proporcionarle una respuesta detallada:

Tenga en cuenta que es mejor no utilizar la combinación de nombre de usuario y contraseña en cada solicitud que realice. Lo mejor es autenticar al usuario, generar un token del lado del servidor, comunicarlo al cliente (por ejemplo, en una cookie) y usar ese token como autenticación para las solicitudes posteriores. Este enlace puede guiarlo en ese proceso: enlace .

    
respondido por el Michael 14.04.2014 - 09:56
fuente
0

Si solo necesita proporcionar autenticación, pero los datos transmitidos a través del cable no son confidenciales, hay una mejor manera sin la sobrecarga / latencia de SSL.

Digamos que tienes una aplicación de cliente móvil; primero haga que el usuario se registre o se registre proporcionando su correo electrónico (nombre de usuario) y contraseña en un formulario web separado (que no forma parte de la aplicación o del servicio REST). Luego, al registrarse con éxito, responde con una clave de usuario (puede ser una clave secreta compartida almacenada en la cuenta de usuario en el servidor (base de datos) para el cifrado simétrico o una clave pública para el cifrado asimétrico donde la clave privada correspondiente se almacena en la cuenta del usuario). en el servidor (base de datos). Todo esto se hace mediante un formulario web sobre SSL.

Ahora, cuando el usuario abre la aplicación cliente, debe solicitar sus credenciales que se enviarán con cada solicitud al servicio RESTful. Deben proporcionar su nombre, contraseña y clave de cifrado que recibieron previamente. Esto solo debe hacerse una vez. La aplicación luego proporciona un encabezado http con cada solicitud que se parece a esto:

AUTENTIFICAR > nombre de usuario: marca de hora: cifrada {contraseña: marca de hora} / AUTHENTICATE >

Tenga en cuenta que tanto la contraseña como la marca de tiempo dentro de {} se cifran con la clave del usuario. La marca de tiempo se actualiza con cada solicitud única.

Implemente un filtro de autenticación en el servidor que haga lo siguiente:

Primero verifique la marca de tiempo y si está vencida (digamos, más de 1 segundo) envíe un código de respuesta HTTP NO AUTORIZADO. Si la marca de tiempo es válida, busque el nombre de usuario en la base de datos de su cuenta de usuario. Si no se encuentra, envíe una respuesta HTTP NO AUTORIZADA. Si se encuentra el nombre de usuario, busque la clave de cifrado almacenada para ese usuario (recuerde que esto puede ser una clave secreta compartida o la clave privada para la clave pública de los usuarios). Descifre el cifrado {contraseña: marca de tiempo}. La contraseña descifrada debe coincidir con la contraseña de los usuarios almacenada en su base de datos (la contraseña también podría estar incrustada en la base de datos usando otra clave para mayor seguridad) y la marca de tiempo descifrada también debe coincidir con la marca de tiempo no cifrada enviada en el encabezado AUTENTICADO arriba. De lo contrario, envíe un código de respuesta HTTP NO AUTORIZADO. Si tiene éxito, la solicitud se ha autenticado sin el uso de cookies / sesiones.

También puede almacenar en caché los detalles del usuario para evitar realizar una búsqueda en la base de datos con cada solicitud.

Ahora, si alguien está indagando e intercepta la solicitud, no podrá reutilizarla para obtener acceso porque la marca de tiempo no será válida o, si actualizan la marca de hora sin cifrar para que sea válida, no coincidirá con la encriptada marca de tiempo (después de que el filtro de autenticación lo descifre).

Otra ventaja de este enfoque sobre el uso de una sola clave de aplicación es que ahora tiene un control completo sobre quién puede acceder a su servicio al poner una fecha de vencimiento en la cuenta de usuario en la base de datos (implementando efectivamente un servicio basado en suscripción). Esto es genial porque al principio es posible que desee obtener la mayor cantidad de usuarios posible con una suscripción de prueba (gratis por un año, por ejemplo) y luego bloquear el acceso a ese usuario si no ha realizado el pago para extender la fecha de vencimiento de la cuenta:)

    
respondido por el user3598746 10.05.2014 - 10:04
fuente

Lea otras preguntas en las etiquetas