Início > Programação, Segurança > Implementação de Autorização com Token Utilizando RESTEasy

Implementação de Autorização com Token Utilizando RESTEasy

Gosto bastante de desenvolver orientado a aspectos. A especificação JAX-RS possibilita implementar um mecanismo de autorização simples para seu web service REST. Um mecanismo de segurança simples ainda é melhor do que não ter segurança e a segurança deve ser definida como parte da arquitetura e não como uma funcionalidade.

Nesse exemplo, vamos mostrar como implementar um mecanismo de autorização baseado em token que é verificado em um interceptador do RESTEasy. Você poderia utilizar um ContainerRequestFilter ao invés do interceptor, mas você teria que utilizar a annotation @NameBinding em conjunto com a sua annotation para só então poder utilizá-la para anotar seu filtro.

1. Crie um enum que será utilizado para parametrizar sua anotação.

public enum Role {
   AUTHENTICATION_REQUIRED;
}

2. Crie uma anotação que utiliza a enum definida anteriormente para criar uma política de segurança. Essa anotação e aquela enum serão verificadas no interceptador. Você poderia utilizar outros métodos para identificar os recursos onde a política se aplicará, mas a combinação de enum e anotação é simples e elegante.

@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD })
public @interface SecurityPolicy {
   Role[] value() default {};
}

3. Implemente um interceptador que verifica a anotação criada e a presença do atributo “TOKEN” no header da request. Note que além da anotação que criamos anteriormente (SecurityPolicy), estamos testando as anotações padrão PermitAll e DenyAll que poderiam estar anotando o recurso e são mais abrangentes que a nossa. Se tudo é permitido ou se tudo é negado, não faz sentido fazer uma verificação mais granular.

@Provider
@ServerInterceptor
public class SecurityInterceptor implements PreProcessInterceptor {
   @Override
   public ServerResponse preProcess(HttpRequest request, 
        ResourceMethod methodInvoked) 
      throws Failure, WebApplicationException {
      Method method = methodInvoked.getMethod();
      if (method.isAnnotationPresent(PermitAll.class)) {
         return null;
      }
      if (method.isAnnotationPresent(DenyAll.class)) {
         return new ServerResponse("Não pode acessar esse recurso",
         Status.UNAUTHORIZED.getStatusCode(), 
         new Headers<Object>());
      }
      if (method.isAnnotationPresent(SecurityPolicy.class)) {
         SecurityPolicy rolesAnnotation = 
           method.getAnnotation(SecurityPolicy.class);
         List<Role> roles = Arrays.asList(rolesAnnotation.value());
         if (roles.contains(Role.AUTHENTICATION_REQUIRED)) {
            HttpHeaders headers = request.getHttpHeaders();
            List<String> authorization = 
              headers.getRequestHeader("TOKEN");
            if(authorization != null && !authorization.isEmpty())
            {
               String token = authorization.get(0); 
               boolean autorizado = /*regras de autorizacao*/;
               if(autorizado){
                  // Deve-se retornar nulo para que o 
                  // processamento da request continue normalmente
                  return null;
               }
            }
            return new ServerResponse("Usuário não autorizado", 
              Status.FORBIDDEN.getStatusCode(),
              new Headers<Object>());
         }
      }
      // Deve-se retornar nulo para que o 
      // processamento da request continue normalmente
      return null;
   }
}

4. Crie um recurso e anote o método que exige a aplicação da política de segurança

@Path("/usuario")
public class UsuarioResource {
 
  @EJB
   private UsuarioService service;

   @GET
   @SecurityPolicy(Role.AUTHENTICATION_REQUIRED)
   @Path("/buscar")
   @Produces(MediaType.APPLICATION_JSON)
   public Response buscar(@PathParam("id") String id) {
      try {
         Usuario usuario = service.buscar(id);
         ResponseUsuario respUsuario = new ResponseUsuario();
         respUsuario.setNome(usuario.getNome());
         return Response.status(Response.Status.OK).
            entity(respUsuario).
            header("Content-type", "application/json; charset=utf-8").
            build();
      } catch (ServicoException e) {
          return Response.status(Response.Status.FORBIDDEN).
            entity("Nao foi possivel localizar o usuario.").
            header("Content-type", "application/json; charset=utf-8").
            build();
      }
      return Response.status(Response.Status.UNAUTHORIZED).
        entity("Usuário não autorizado.").
        header("Content-type", "application/json; charset=utf-8").
        build();
   }
}

Você poderia utilizar algum navegador para testar o funcionamento do seu web service, mas prefiro utilizar o SOAPUI. Se você tiver alguma problema relacionado a certificado do Java, dê uma olhada nesse artigo.

token

Figura 1 – Interface do SOAPUI

Note o parâmetro “TOKEN” que passamos no cabeçalho da request. O ideal é que o valor seja obtido do próprio web service, talvez acessando o banco de dados, e que este tenha um tempo de expiração que faça sentido para o negócio e para alguma política de segurança da informação de nível operacional.

Referências

1. [http://stackoverflow.com/questions/26777083/best-practice-for-rest-token-based-authentication-with-jax-rs-and-jersey
2. [https://www.infoq.com/br/news/2012/10/autenticacao-rest
3. [http://blog.rivendel.com.br/2013/06/07/seguranca-em-apis-rest-parte-1/
4. [http://www.slideshare.net/stormpath
5. [http://www.developerscrappad.com/1814/java/java-ee/rest-jax-rs/java-ee-7-jax-rs-2-0-simple-rest-api-authentication-authorization-with-custom-http-header/
6. [http://stackoverflow.com/questions/26777083/best-practice-for-rest-token-based-authentication-with-jax-rs-and-jersey
7. [https://www.mkyong.com/webservices/jax-rs/get-http-header-in-jax-rs/
8. [http://howtodoinjava.com/resteasy/jax-rs-resteasy-basic-authentication-and-authorization-tutorial/
9. [http://howtodoinjava.com/resteasy/jax-rs-2-0-resteasy-3-0-2-final-security-tutorial/[

Anúncios
  1. Nenhum comentário ainda.
  1. 18/03/2017 às 7:20 PM

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s

%d blogueiros gostam disto: