JAX-RS: CORS
Introdução
No desenvolvimento de aplicações web, frequentemente precisamos que um frontend (como uma aplicação Angular ou React) consuma APIs REST hospedadas em domínios diferentes. Por padrão, navegadores web implementam uma política de segurança chamada Same-Origin Policy, que impede que scripts em uma página interajam com recursos de um domínio diferente. O CORS (Cross-Origin Resource Sharing) é um mecanismo que permite que recursos restritos em uma página web sejam solicitados a partir de outro domínio fora do domínio do qual o recurso foi servido.
Este guia irá explicar:
O que é CORS e como funciona.
Como habilitar CORS em aplicações JAX-RS usando Jakarta EE (pacotes
jakarta.ws.rs
).Como configurar e responder às requisições OPTIONS que os navegadores enviam durante uma solicitação CORS.
O que é CORS?
Conceito
CORS (Cross-Origin Resource Sharing) é um padrão de segurança que permite que um servidor indique explicitamente que sua API pode ser acessada por outros domínios. Isso é feito através do uso de cabeçalhos HTTP que informam aos navegadores quais origens são permitidas para acessar os recursos.
Same-Origin Policy
A Same-Origin Policy é uma medida de segurança implementada pelos navegadores que restringe como um documento ou script carregado de uma origem pode interagir com recursos de outra origem. Uma "origem" é definida pelo esquema (protocol), host (domínio) e porta.
Como o CORS Funciona
Quando uma aplicação frontend faz uma requisição para um domínio diferente, o navegador verifica se a resposta do servidor inclui os cabeçalhos CORS apropriados que permitem essa interação. Se os cabeçalhos estiverem presentes e forem válidos, o navegador permite a resposta; caso contrário, a requisição é bloqueada.
Existem dois tipos principais de requisições CORS:
Simple Requests (Requisições Simples): GET, POST ou HEAD com tipos de conteúdo simples.
Preflighted Requests (Requisições Preflight): Para métodos diferentes ou cabeçalhos personalizados, o navegador envia uma requisição OPTIONS antes da requisição real para verificar se é permitido.
Habilitando CORS em JAX-RS com Jakarta EE
Para permitir que seu serviço JAX-RS responda a requisições CORS, você precisa configurar seu aplicativo para adicionar os cabeçalhos CORS apropriados nas respostas.
Método 1: Usando um Filtro ContainerResponseFilter
Uma maneira eficaz de habilitar CORS em JAX-RS é criando um filtro que intercepta as respostas e adiciona os cabeçalhos necessários.
Passo 1: Criar o Filtro CORS
Explicação dos Cabeçalhos:
Access-Control-Allow-Origin: Especifica quais origens têm permissão para acessar o recurso.
*
significa todas as origens.Access-Control-Allow-Headers: Lista de cabeçalhos permitidos na requisição.
Access-Control-Allow-Credentials: Indica se a resposta pode ser exposta quando o valor do cabeçalho
credentials
étrue
.Access-Control-Allow-Methods: Métodos HTTP permitidos.
Access-Control-Max-Age: Tempo em segundos que o resultado da requisição preflight pode ser armazenado em cache.
Passo 2: Registrar o Filtro
Dependendo da forma como você está configurando seu aplicativo JAX-RS, você precisa registrar o filtro.
Usando Application Subclass:
Usando arquivos de configuração (por exemplo, no web.xml
):
Se você estiver usando um framework que detecta automaticamente as classes com a anotação @Provider
, como o Jersey, não precisa registrar o filtro manualmente.
Método 2: Configurando Cabeçalhos em Recursos Específicos
Você também pode adicionar os cabeçalhos CORS diretamente nas respostas dos recursos, mas isso é menos recomendado devido à repetição.
Lidando com Requisições OPTIONS (Preflight)
O que é uma Requisição Preflight?
Quando uma requisição não é simples (por exemplo, usa um método diferente de GET, POST ou HEAD, ou inclui cabeçalhos personalizados), o navegador envia uma requisição OPTIONS antes da requisição real. Isso é chamado de Preflight Request.
A requisição OPTIONS é usada para verificar se a operação é permitida pelo servidor.
Exemplo de Requisição OPTIONS
Cabeçalhos da Requisição OPTIONS:
Cabeçalhos da Resposta Esperada:
Habilitando Suporte a OPTIONS em JAX-RS
Para responder corretamente às requisições OPTIONS, você precisa garantir que seu serviço possa lidar com elas.
Método 1: Usando o Filtro para Responder a OPTIONS
Modifique o filtro para verificar se a requisição é do método OPTIONS e ajustar a resposta.
Método 2: Criar um Recurso Específico para OPTIONS
Você pode adicionar um método em seus recursos para lidar com o método OPTIONS.
Nota: Este método precisa ser repetido em cada recurso, o que não é ideal. O uso de um filtro é preferível.
Exemplo Completo
Vamos reunir tudo em um exemplo completo.
Estrutura do Projeto
src/main/java
com.exemplo
ApplicationConfig.java
(classe de configuração)CorsFilter.java
(filtro CORS)resources
UsuarioResource.java
(recurso JAX-RS)
Arquivos
CorsFilter.java
ApplicationConfig.java
UsuarioResource.java
Testando a Configuração CORS
Para verificar se o CORS está configurado corretamente:
Inicie o Servidor: Execute sua aplicação em um servidor compatível com Jakarta EE (por exemplo, Payara, WildFly, TomEE).
Faça uma Requisição de Outro Domínio: Use uma ferramenta como o
curl
ou um frontend hospedado em outro domínio para fazer uma requisição ao seu serviço.
Exemplo de Requisição OPTIONS com curl
:
Resposta Esperada:
Considerações de Segurança
Access-Control-Allow-Origin: Evite usar
*
em ambientes de produção. Em vez disso, especifique os domínios permitidos.String origin = requestContext.getHeaderString("Origin"); if (isOriginAllowed(origin)) { responseContext.getHeaders().add("Access-Control-Allow-Origin", origin); }Access-Control-Allow-Credentials: Se você precisar suportar credenciais (cookies, autenticação HTTP), não pode usar
*
noAccess-Control-Allow-Origin
. Deve especificar a origem.Validação de Métodos e Cabeçalhos: Verifique se os métodos e cabeçalhos permitidos são realmente necessários.
Alternativas e Ferramentas
Usando Bibliotecas de Terceiros
Existem bibliotecas que facilitam a configuração do CORS, como:
CORS Filter do Container: Alguns servidores de aplicação fornecem filtros CORS embutidos que podem ser configurados no
web.xml
.
Exemplo no web.xml
:
Usando Frameworks JAX-RS Específicos
Alguns frameworks JAX-RS oferecem anotações ou configurações para habilitar CORS de forma mais simples.
Exemplo com Jersey (usando Jakarta EE):
Resumo
CORS é essencial para permitir que aplicações frontend acessem APIs em domínios diferentes.
Em JAX-RS com Jakarta EE, o método mais eficaz para habilitar CORS é através de um ContainerResponseFilter que adiciona os cabeçalhos CORS a todas as respostas.
É importante lidar corretamente com as requisições OPTIONS enviadas pelos navegadores durante o preflight, adicionando os cabeçalhos necessários e retornando uma resposta adequada.
Sempre considere as melhores práticas de segurança, especificando origens permitidas e limitando métodos e cabeçalhos conforme necessário.
Exercícios Práticos
Implementar CORS em uma API Existente: Pegue uma API JAX-RS com Jakarta EE que você já tenha e habilite o CORS usando um filtro.
Especificar Origens Permitidas: Modifique o filtro para permitir apenas determinadas origens, e teste o acesso a partir de origens permitidas e não permitidas.
Suportar Credenciais: Configure o CORS para permitir o envio de credenciais (cookies, autenticação HTTP), ajustando os cabeçalhos adequadamente.
Usar um Framework: Se estiver usando um framework como o Spring Boot com suporte a Jakarta EE, explore como habilitar CORS usando as ferramentas fornecidas pelo framework.
Conclusão
Habilitar CORS em aplicações JAX-RS usando Jakarta EE é um passo essencial para permitir que aplicações frontend interajam com suas APIs de forma segura e eficaz. Compreender como o CORS funciona e como configurá-lo corretamente garante que sua aplicação seja acessível e mantenha práticas de segurança adequadas.
Espero que este guia tenha esclarecido como habilitar e configurar o CORS em suas aplicações JAX-RS usando Jakarta EE e como lidar com as requisições OPTIONS que os navegadores enviam durante as interações CORS.
Observações Finais
Transição de javax. para jakarta.**: Com a evolução do Java EE para Jakarta EE, os pacotes mudaram de
javax.*
parajakarta.*
. É importante atualizar as dependências e importações ao migrar sua aplicação.Compatibilidade: Certifique-se de que seu servidor de aplicação é compatível com Jakarta EE 9 ou superior para utilizar os pacotes
jakarta.*
.Atualização de Dependências: Verifique as versões de suas bibliotecas (como Jersey, RESTEasy, etc.) para garantir compatibilidade com Jakarta EE.
Nota: Este guia foi atualizado para utilizar os pacotes jakarta.ws.rs
conforme solicitado.