Come abilitare le richieste di domini incrociati sui servizi web JAX-RS?

Ho sviluppato un set di servizi web riposanti. Non è stato ansible richiamare nessuno di questi metodi dai client remoti a causa dell’errore No 'Access-Control-Allow-Origin' header is present on the requested resource.

I servizi funzionano perfettamente su localhost. C’è qualche modifica o configurazione da fare sul lato server per risolvere il problema. vale a dire per abilitare richieste interdominio.

Sto usando WildFly 8, JavaEE 7

Mi stavo chiedendo la stessa cosa, quindi dopo un po ‘di ricerche ho scoperto che il modo più semplice era semplicemente utilizzare un ContainerResponseFilter JAX-RS per aggiungere le intestazioni CORS pertinenti. In questo modo non è necessario sostituire l’intero stack dei servizi Web con CXF (Wildfly utilizza CXF in qualche modo, ma non sembra che lo usi per JAX-RS, forse solo JAX-WS).

Indipendentemente se si utilizza questo filtro, aggiungerà le intestazioni a ogni webservice REST.

 package com.yourdomain.package; import java.io.IOException; import javax.ws.rs.container.ContainerRequestContext; import javax.ws.rs.container.ContainerResponseContext; import javax.ws.rs.container.ContainerResponseFilter; import javax.ws.rs.ext.Provider; @Provider public class CORSFilter implements ContainerResponseFilter { @Override public void filter(final ContainerRequestContext requestContext, final ContainerResponseContext cres) throws IOException { cres.getHeaders().add("Access-Control-Allow-Origin", "*"); cres.getHeaders().add("Access-Control-Allow-Headers", "origin, content-type, accept, authorization"); cres.getHeaders().add("Access-Control-Allow-Credentials", "true"); cres.getHeaders().add("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, HEAD"); cres.getHeaders().add("Access-Control-Max-Age", "1209600"); } } 

Poi, quando ho provato con curl, la risposta aveva le intestazioni CORS:

 $ curl -D - "http://localhost:8080/rest/test" HTTP/1.1 200 OK X-Powered-By: Undertow 1 Access-Control-Allow-Headers: origin, content-type, accept, authorization Server: Wildfly 8 Date: Tue, 13 May 2014 12:30:00 GMT Connection: keep-alive Access-Control-Allow-Origin: * Access-Control-Allow-Credentials: true Transfer-Encoding: chunked Content-Type: application/json Access-Control-Max-Age: 1209600 Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS, HEAD 

La mia comprensione è che è l’annotazione @Provider che dice al runtime JAX-RS di usare il filtro, senza l’annotazione non succede nulla.

Ho avuto l’idea di usare ContainerResponseFilter da un esempio di Jersey .

Stavo affrontando un problema simile e avevo provato a utilizzare la soluzione di @Alex Petty, ma oltre a dover impostare le intestazioni CORS su ciascun endpoint JAX-RS della mia class, in quanto tale:

 @GET @Produces(MediaType.APPLICATION_JSON) public Response getMemberList() { List memberList = memberDao.listMembers(); members.addAll(memberList); return Response .status(200) .header("Access-Control-Allow-Origin", "*") .header("Access-Control-Allow-Headers", "origin, content-type, accept, authorization") .header("Access-Control-Allow-Credentials", "true") .header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, HEAD") .header("Access-Control-Max-Age", "1209600") .entity(memberList) .build(); } 

Ho dovuto definire ulteriormente un endpoint OPTIONS catch-all che restituirebbe le intestazioni CORS per qualsiasi altra richiesta OPTIONS nella class e quindi catturerebbe tutti gli endpoint del tipo:

 @OPTIONS @Path("{path : .*}") public Response options() { return Response.ok("") .header("Access-Control-Allow-Origin", "*") .header("Access-Control-Allow-Headers", "origin, content-type, accept, authorization") .header("Access-Control-Allow-Credentials", "true") .header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, HEAD") .header("Access-Control-Max-Age", "1209600") .build(); } 

Solo dopo averlo fatto, potrei utilizzare correttamente i miei endpoint API JAX-RS dai client Jquery Ajax su altri domini o host.

Ho trovato un modo ancora più semplice (specifico per RestEasy) per abilitare CORS su Wildfly senza utilizzare un filtro e dove è ansible controllare la configurazione dell’intestazione di risposta dell’API a livello di risorsa.

Per esempio:

 @GET @Produces(MediaType.APPLICATION_JSON) public Response getMemberList() { List memberList = memberDao.listMembers(); members.addAll(memberList); return Response .status(200) .header("Access-Control-Allow-Origin", "*") .header("Access-Control-Allow-Headers", "origin, content-type, accept, authorization") .header("Access-Control-Allow-Credentials", "true") .header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, HEAD") .header("Access-Control-Max-Age", "1209600") .entity(memberList) .build(); } 

Ho avuto la fortuna di configurare la condivisione delle risorse di origine incrociata (CORS) per la mia API (su Wildfly) utilizzando questa libreria:

  com.thetransactioncompany cors-filter 2.1  

È molto facile da configurare. Basta aggiungere la dipendenza sopra al tuo pom e quindi aggiungere la seguente configurazione alla sezione webapp del tuo file web.xml.

  CORS com.thetransactioncompany.cors.CORSFilter  cors.allowGenericHttpRequests true   cors.allowOrigin *   cors.allowSubdomains false   cors.supportedMethods GET, HEAD, POST, DELETE, OPTIONS   cors.supportedHeaders *   cors.supportsCredentials true   cors.maxAge 3600     CORS *  

Puoi anche configurarlo con un file di proprietà, se preferisci. Questa libreria funziona come un fascino e ti offre molta flessibilità di configurazione!

Nessuna delle altre risposte ha funzionato per me, ma questo ha fatto:

import javax.ws.rs.core.Response;

Quindi modificare il tipo di restituzione del metodo di servizio in Response e modificare l’istruzione return in:

 return Response.ok(resp).header("Access-Control-Allow-Origin", "*").build(); 

Dove resp è l’object di risposta originale.

È inoltre ansible implementare javax.ws.rs.core.Feature come di seguito per implementare CORS.

 import javax.ws.rs.core.Feature; import javax.ws.rs.core.FeatureContext; import javax.ws.rs.ext.Provider; import org.jboss.resteasy.plugins.interceptors.CorsFilter; @Provider public class CorsFeature implements Feature { @Override public boolean configure(FeatureContext context) { CorsFilter corsFilter = new CorsFilter(); corsFilter.getAllowedOrigins().add("*"); context.register(corsFilter); return true; } } 

Solo per aggiungere qualcosa ad altre risposte. Permettere * è un po ‘pericoloso. Quello che si può fare è configurare un database con l’origine consentita (può essere un file)

Quindi quando la richiesta arriva puoi fare:

 // this will return you the origin String referers[] = requestContext.getHeaders().get("referer") // then search in your DB if the origin is allowed if(referers != null && referers.lenght == 1 && isAllowedOriging(referers[0])){ containerResponseContext.getHeaders().add("Access-Control-Allow-Origin", referers[0]); containerResponseContext.getHeaders().add("Access-Control-Allow-Headers", "origin, content-type, accept, authorization, ); containerResponseContext.getHeaders().add("Access-Control-Allow-Credentials", "true"); containerResponseContext.getHeaders().add("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, HEAD"); containerResponseContext.getHeaders().add("Access-Control-Max-Age", "1209600"); } 

In questo modo non permetterò a tutti.