CORS em JAX-RS

CORS em JAX-RS

1. Visão geral

Neste artigo rápido, aprenderemos como habilitarCORS (Cross-Origin Resource Sharing) em um sistema baseado emJAX-RS. Vamos configurar um aplicativo no topo deJAX-RS para habilitar o mecanismoCORS.

2. Como ativar o mecanismo CORS

Existem duas maneiras pelas quais podemos ativar o CORS no JAX-RS. A primeira e a maneira mais básica é criar um filtro para injetar o cabeçalho de resposta necessário no tempo de execução em cada solicitação. O outro é adicionar manualmente um cabeçalho apropriado em cada ponto de extremidade da URL.

Idealmente, a primeira solução deve ser usada; no entanto, quando isso não é uma opção, a opção mais manual é técnica OK também.

2.1. Usando o Filtro

JAX-RS tem a interfaceContainerResponseFilter - implementada pelos filtros de resposta do contêiner. Normalmente, essa instância de filtro é aplicada globalmente a qualquer resposta HTTP.

Implementaremos essa interface para criar um filtro personalizado que injetará o cabeçalhoAccess-Control-Allow-* em cada solicitação de saída e habilitará o mecanismoCORS:

@Provider
public class CorsFilter implements ContainerResponseFilter {

    @Override
    public void filter(ContainerRequestContext requestContext,
      ContainerResponseContext responseContext) throws IOException {
          responseContext.getHeaders().add(
            "Access-Control-Allow-Origin", "*");
          responseContext.getHeaders().add(
            "Access-Control-Allow-Credentials", "true");
          responseContext.getHeaders().add(
           "Access-Control-Allow-Headers",
           "origin, content-type, accept, authorization");
          responseContext.getHeaders().add(
            "Access-Control-Allow-Methods",
            "GET, POST, PUT, DELETE, OPTIONS, HEAD");
    }
}

Alguns pontos aqui:

  • Filtros que implementamContainerResponseFilter devem ser explicitamente anotados com@Provider para serem descobertos pelo tempo de execução JAX-RS

  • Estamos injetando ‘Access-Control-Allow-‘ cabeçalho com ‘', isso significa que qualquer endpoint de URL para esta instância do servidor pode ser acessado por meio de qualquer domínio; se quisermos restringir o acesso entre domínios explicitamente, temos que mencionar esse domínio neste cabeçalho

2.2. Usando a modificação do cabeçalho em cada terminal

Conforme declarado anteriormente, podemos injetar explicitamente o cabeçalho ‘Access-Control-Allow-*’ no nível do terminal também:

@GET
@Path("/")
@Produces({MediaType.TEXT_PLAIN})
public Response index() {
    return Response
      .status(200)
      .header("Access-Control-Allow-Origin", "*")
      .header("Access-Control-Allow-Credentials", "true")
      .header("Access-Control-Allow-Headers",
        "origin, content-type, accept, authorization")
      .header("Access-Control-Allow-Methods",
        "GET, POST, PUT, DELETE, OPTIONS, HEAD")
      .entity("")
      .build();
}

Um ponto a ser observado aqui é se estivermos tentando habilitarCORS em um aplicativo grande, não devemos tentar este método porque, neste caso, temos que injetar manualmente o cabeçalho em cada endpoints de URL, o que introduzirá a sobrecarga.

No entanto, essa técnica pode ser usada em aplicativos, onde precisamos habilitarCORS em apenas alguns dos endpoints de URL.

3. Teste

Depois que o aplicativo é ativado, podemos testar os cabeçalhos usando os comandos curl. Um exemplo de saída de cabeçalho deve ser algo como abaixo:

HTTP/1.1 200 OK
Date : Tue, 13 May 2014 12:30:00 GMT
Connection : keep-alive
Access-Control-Allow-Origin : *
Access-Control-Allow-Credentials : true
Access-Control-Allow-Headers : origin, content-type, accept, authorization
Access-Control-Allow-Methods : GET, POST, PUT, DELETE, OPTIONS, HEAD
Transfer-Encoding : chunked

Além do mais, podemos criar uma função AJAX simples e verificar a funcionalidade entre domínios:

function call(url, type, data) {
    var request = $.ajax({
      url: url,
      method: "GET",
      data: (data) ? JSON.stringify(data) : "",
      dataType: type
    });

    request.done(function(resp) {
      console.log(resp);
    });

    request.fail(function(jqXHR, textStatus) {
      console.log("Request failed: " + textStatus);
    });
};

Claro, para realmente realizar a verificação, teremos que executá-la em uma origem diferente da API que estamos consumindo.

Você pode fazer isso localmente facilmente executando um aplicativo cliente em uma porta separada -since the port does determine the origin.

4. Conclusão

Neste artigo, mostramos como implementar o mecanismoCORS em aplicativos baseados em JAX-RS.

Como sempre, o código-fonte completo está disponívelover on GitHub.