ApiRest security with Jersey

0

I have made an Api Rest in java with maven jersey.

But the time has come to protect her. How should I do it?

I have seen JWT to do the practice, but I'm not sure how it should correctly integrate.

I can now send and receive the header that is where the key that I generated must be sent, I have a class which compares the key and the data, should I send that class in my Rest methods to compare if the key is correct to continue, if not, to refuse access?

Or what would be the best practice, or if you know of an example of how it should be integrated would be more than great.

    
asked by Chriz CR 30.12.2016 в 18:32
source

1 answer

1

There are several security schemes that you can implement, you can read the answer to this question something similar.

To give you a concrete solution I will give you an example that I use to secure an API in Jersey using Tokens.

First, once the user logs into your API, you must provide an Accesstoken access token, this token the client must send in the header in each HTTPRequest that he makes to the server after it is achieved.

The header will be called Accesstoken, here a correction since custom headers should start with the prefix X- so you should call it X-Accesstoken or use the standard HTTP header called Authorization.

Now to capture this header the best option is to create an Authorization Filter where I capture this header, in this filter the token is valid and I get the user in this case the Accesstoken stores it in the DB but for better performance you can store it in a In-memory database like Redis.

@NameBinding
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(value = RetentionPolicy.RUNTIME)
public @interface MiFiltroAutorizacion {}

@ MiFiltroAutorizacion
public class MiFiltroAutorizacionFilter implements ContainerRequestFilter {

    @Override
    public void filter(ContainerRequestContext requestContext) throws IOException {
        ClienteAccesstokenDAO clienteAccesstokenDAO = new ClienteAccesstokenDAO();

        if(requestContext.getHeaders().get("Accesstoken") != null){
            String accesstoken =requestContext.getHeaders().get("Accesstoken").get(0).toString();
            ClienteAccesstoken clienteAccesstoken = clienteAccesstokenDAO.findByToken(accesstoken);

            if(clienteAccesstoken == null)
                requestContext.abortWith(
                        Response.status(Response.Status.UNAUTHORIZED)
                                .build());

        }
    }
}

Now you must declare this filter in the web.xml file in the section where you configure your Jersey servlet by adding.

    <init-param>
        <param-name>jersey.config.server.provider.classnames</param-name>
        <param-value>com.stackoverflow.es.filtros.MiFiltroAutorizacionFilter</param-value>
    </init-param>

Now in each service of your Rest API you must explicitly specify if this service is insured or not with the annotation @MiFiltroAutorizacion in the following way.

@GET
@Path("estadodecuenta")
@Produces(MediaType.APPLICATION_JSON)
@MiFiltroAutorizacion
public Response miRecursoProtegido(@HeaderParam("Accesstoken") String accesstoken) {

    .....
    return Response.ok().build();
}

If you do not put the annotation in the service, it simply will not go through the authorization filter and therefore it is assumed to be a public resource.

If you want to obtain the user of the 'session' or rather the user who owns the Accesstoken, you can use the ThreadLocal class to store the user of the 'session' at the level of Thread

public class MiAppContext {
    public static final ThreadLocal<Usuario> usuarioThreadLocal = new ThreadLocal<Usuario>();
}

You store the user in the ThreadLocal from the filter

@ MiFiltroAutorizacion
public class MiFiltroAutorizacionFilter implements ContainerRequestFilter {

    @Override
    public void filter(ContainerRequestContext requestContext) throws IOException {
        ClienteAccesstokenDAO clienteAccesstokenDAO = new ClienteAccesstokenDAO();

        if(requestContext.getHeaders().get("Accesstoken") != null){
            String accesstoken =requestContext.getHeaders().get("Accesstoken").get(0).toString();
            ClienteAccesstoken clienteAccesstoken = clienteAccesstokenDAO.findByToken(accesstoken);

            MiAppContext.usuarioThreadLocal.set(clienteAccesstoken.getUsuario()); // Agregar usuario al ThreadLocal

            if(clienteAccesstoken == null)
                requestContext.abortWith(
                        Response.status(Response.Status.UNAUTHORIZED)
                                .build());

        }
    }
}

And then in the service you get the user in this way

@GET
@Path("estadodecuenta")
@Produces(MediaType.APPLICATION_JSON)
@MiFiltroAutorizacion
public Response miRecursoProtegido(@HeaderParam("Accesstoken") String accesstoken) {
    Usuario usuarioSesion = MiAppContext.usuarioThreadLocal.get();
    .....
    return Response.ok().build();
}
    
answered by 30.12.2016 / 19:08
source