2012-01-15 20 views
7

Tengo una aplicación web que necesita permitir a los usuarios que utilizan diferentes clientes web (navegador, aplicación móvil nativa, etc.) para registrarse. Después de iniciar sesión, pueden acceder a contenido restringido o a su propio contenido (como las entradas que crean, etc.).jax-rs rest webservice autenticación y autorización

Lo que hice hasta ahora: He creado un JAX-RS servicio web reposo (que celebro mi solicitud en GlassFish) que expone los métodos siguientes:

  • registro - de la POST de usuario su nombre de usuario deseado/contraseña/correo electrónico/etc; si el nombre de usuario/correo electrónico es único, se crea una entrada para este usuario en la base de datos (estoy usando Hibernate para la persistencia)
  • nombre de usuario y contraseña de POST. Si están bien, se crea un UUID y se devuelve al usuario (esto se usará como un token para futuras solicitudes). Tengo una tabla llamada logedusers, con userID, token, validSince como columnas.

Aquí es donde me resulta confuso.

Digamos que tengo otro método, getUserEntries, que debe devolver todas las entradas realizadas por el usuario. Para aclarar esto, habrá una tabla de entrada con los siguientes campos: entryId, userId, text.

¿Cuál es el mejor enfoque aquí?

lo que hago ahora, es que me hace una solicitud Obtener y transmitir en el token de la siguiente manera:

localhost:8080/myApp/getUserEntries?token=erf34c34

Después, si el token es válido, aparece el ID de usuario de la mesa logedusers y por motivos en ese userId, obtenga todas las entradas y devuélvalas como json.

Algo como esto:

@GET 
@Path("getUserEntries") 
@Produces(MediaType.APPLICATION_JSON) 
public Response getUserEntries(@QueryParam("token") String token) {  
    String userId=getUserIdFromToken(token); 
    if (userId == null){ 
     return Response.status(Response.Status.UNAUTHORIZED).build(); 
    } else { 
     //get some data associated with that userId, put it in the response object and send it back 
     return Response.ok().entity(response).build(); 
    } 
} 

Sin embargo, ¿qué sucede si tengo más métodos que proporcionan datos si son llamados por un usuario válido?

Tendría que hacer esta comprobación al comienzo de cada método.

Quiero que este proceso sea transparente de autorización

Así, dos grandes preguntas aquí:

  1. Es este diseño bien? El conjunto se autentica con user/pass, el servidor crea y almacena y envía token al usuario, el usuario envía token a futuras solicitudes.
  2. ¿Qué debo hacer si tengo muchos puntos finales que necesitan determinar la identidad del usuario llamante? ¿Puedo marcarlos con algunas anotaciones, utilizar algún tipo de proveedor de seguridad/autenticador (donde puedo agregar mi propia lógica para validar, por ejemplo, verificar para ver si el token no es anterior a 5 días, etc.).

Gracias

Respuesta

2

está bien este diseño? El conjunto se autentica con user/pass, el servidor crea y almacena y envía token al usuario, el usuario envía token a futuras solicitudes.

Está algo bien. El nivel conceptual no es tan malo (siempre que esté bien con el auto registro) pero la interfaz necesita muchos ajustes. Si bien, POST para registrarse e iniciar sesión es correcto, para el resto de su aplicación web, debe extraer la información de identidad del contexto si la necesita, y usar el control de acceso basado en roles en el nivel de método donde pueda.

Tenga en cuenta que su contenedor tiene un conjunto completo de mecanismos de autenticación y soporte de autorización incorporados. Úselos.

¿Qué debo hacer si tengo muchos puntos finales que necesitan determinar la identidad del usuario llamante? ¿Puedo marcarlos con algunas anotaciones, utilizar algún tipo de proveedor de seguridad/autenticador (donde puedo agregar mi propia lógica para validar, por ejemplo, verificar para ver si el token no es anterior a 5 días, etc.).

¿necesitan la identidad? ¿O solo necesitan saber que el usuario puede acceder a ellos? En este último caso, el método más fácil es colocar una anotación @RolesAllowed adecuada en el método, en cuyo punto (con la configuración adecuada, consulte el JEE5 security docs). Si es el primero, debe obtener el objeto HttpServletRequest para la acción actual y llamar a su método getUserPrincipal() para obtener la identidad del usuario (o nulo si aún no ha iniciado sesión). This SO question describe cómo obtener el objeto de solicitud; hay algunas formas posibles de hacerlo, pero recomiendo la inyección a través de una anotación @Resource.

Lo que no haría es permitir que los usuarios proporcionen normalmente su propia identidad a través de @QueryParam; eso es muy abierto al abuso. Puede permitir que pregunten sobre otros usuarios de esa manera, pero luego debe decidir si va a decirles algo o no según si el usuario actual tiene permitido saber algo sobre el otro usuario. Ese es el tipo de problema de seguridad complejo que surge en una aplicación real, y es un buen punto para necesitar la identidad del usuario verificado actual.

Cuestiones relacionadas