Ich entwickle eine Java-Skript-Client-Anwendung. Auf der Serverseite muss ich CORS verarbeiten, alle Dienste, die ich mit JERSEY in JAX-RS geschrieben habe. Mein Code:
@CrossOriginResourceSharing(allowAllOrigins = true)
@GET
@Path("/readOthersCalendar")
@Produces("application/json")
public Response readOthersCalendar(String dataJson) throws Exception {
//my code. Edited by gimbal2 to fix formatting
return Response.status(status).entity(jsonResponse).header("Access-Control-Allow-Origin", "*").build();
}
Ab sofort wird eine Fehlermeldung angezeigt. In der angeforderten Ressource ist kein Header 'Access-Control-Allow-Origin' vorhanden. Origin ' http: // localhost: 8080 ' ist daher kein Zugriff gestattet. ”
Bitte helfen Sie mir dabei.
Danke und Grüße Buddha Puneeth
Antworten:
@CrossOriginResourceSharing
ist eine CXF-Anmerkung, daher funktioniert sie mit Jersey nicht.Bei Jersey verwende ich normalerweise nur a, um mit CORS umzugehen
ContainerResponseFilter
. DieContainerResponseFilter
für Jersey 1 und 2 sind etwas anders. Da Sie nicht erwähnt haben, welche Version Sie verwenden, werde ich beide veröffentlichen.Jersey 2
import java.io.IOException; import javax.ws.rs.container.ContainerRequestContext; import javax.ws.rs.container.ContainerResponseContext; import javax.ws.rs.container.ContainerResponseFilter; @Provider public class CORSFilter implements ContainerResponseFilter { @Override public void filter(ContainerRequestContext request, ContainerResponseContext response) throws IOException { response.getHeaders().add("Access-Control-Allow-Origin", "*"); response.getHeaders().add("Access-Control-Allow-Headers", "CSRF-Token, X-Requested-By, Authorization, Content-Type"); response.getHeaders().add("Access-Control-Allow-Credentials", "true"); response.getHeaders().add("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, HEAD"); } }
Wenn Sie das Scannen von Paketen verwenden, um Anbieter und Ressourcen zu ermitteln, sollte die
@Provider
Annotation die Konfiguration für Sie übernehmen. Wenn nicht, müssen Sie es explizit bei derResourceConfig
oder derApplication
Unterklasse registrieren .Beispielcode zum expliziten Registrieren des Filters mit
ResourceConfig
:final ResourceConfig resourceConfig = new ResourceConfig(); resourceConfig.register(new CORSFilter()); final final URI uri = ...; final HttpServer httpServer = GrizzlyHttpServerFactory.createHttpServer(uri, resourceConfig);
Jersey 1
import com.sun.jersey.spi.container.ContainerRequest; import com.sun.jersey.spi.container.ContainerResponse; import com.sun.jersey.spi.container.ContainerResponseFilter; @Provider public class CORSFilter implements ContainerResponseFilter { @Override public ContainerResponse filter(ContainerRequest request, ContainerResponse response) { response.getHttpHeaders().add("Access-Control-Allow-Origin", "*"); response.getHttpHeaders().add("Access-Control-Allow-Headers", "CSRF-Token, X-Requested-By, Authorization, Content-Type"); response.getHttpHeaders().add("Access-Control-Allow-Credentials", "true"); response.getHttpHeaders().add("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, HEAD"); return response; } }
web.xml Konfiguration können Sie verwenden
Oder
ResourceConfig
du kannst es tunresourceConfig.getContainerResponseFilters().add(new CORSFilter());
Oder Paket-Scannen mit dem
@Provider
Anmerkung.BEARBEITEN
Bitte beachten Sie, dass das obige Beispiel verbessert werden kann. Sie müssen mehr über die Funktionsweise von CORS wissen. Bitte sehen Sie hier . Zum einen erhalten Sie die Überschriften für alle Antworten. Dies ist möglicherweise nicht wünschenswert. Möglicherweise müssen Sie nur den Preflight (oder die OPTIONEN) bearbeiten. Wenn Sie einen besser implementierten CORS-Filter sehen möchten, können Sie den Quellcode für RESTeasy überprüfen
CorsFilter
AKTUALISIEREN
Deshalb habe ich beschlossen, eine korrektere Implementierung hinzuzufügen. Die obige Implementierung ist faul und fügt allen Anforderungen alle CORS-Header hinzu. Der andere Fehler ist, dass es nur ein ist die Anforderung immer noch verarbeitet Antwortfilter handelt. Dies bedeutet, dass beim Eingang der Preflight-Anforderung, bei der es sich um eine OPTIONS-Anforderung handelt, keine OPTIONS-Methode implementiert ist, sodass wir eine 405-Antwort erhalten, die falsch ist.
So sollte es funktionieren. Es gibt also zwei Arten von CORS-Anfragen: einfache Anfragen und Preflight-Anfragen . Bei einer einfachen Anfrage sendet der Browser die eigentliche Anfrage und fügt den
Origin
Anforderungsheader hinzu. Der Browser erwartet, dass die Antwort denAccess-Control-Allow-Origin
Header enthält, und gibt an, dass der Ursprung desOrigin
Headers zulässig ist. Damit es als "einfache Anfrage" betrachtet werden kann, muss es die folgenden Kriterien erfüllen:Accept
Accept-Language
Content-Language
Content-Type
DPR
Save-Data
Viewport-Width
Width
Content-Type
Header sind:application/x-www-form-urlencoded
multipart/form-data
text/plain
Wenn die Anfrage nicht alle drei Kriterien erfüllt, wird eine Preflight-Anfrage gestellt. Dies ist eine OPTIONS-Anforderung, die an den Server gesendet wird. bevor die eigentliche Anforderung gestellt wird. Es enthält verschiedene
Access-Control-XX-XX
Header, und der Server sollte auf diese Header mit eigenen CORS-Antwortheadern antworten. Hier sind die passenden Header:Mit dem
Origin
Anforderungsheader ist der Wert die Ursprungsserverdomäne, und die AntwortAccess-Control-Allow-Origin
sollte entweder dieselbe Adresse sein oder*
angeben, dass alle Ursprünge zulässig sind.Wenn der Client versucht, Header manuell festzulegen, die nicht in der obigen Liste enthalten sind, legt der Browser den
Access-Control-Request-Headers
Header fest, wobei der Wert eine Liste aller Header ist, die der Client festlegen möchte. Der Server sollte mit einemAccess-Control-Allow-Headers
Antwortheader antworten , wobei der Wert eine Liste der zulässigen Header ist.Der Browser stellt auch die ein
Access-Control-Request-Method
Anforderungsheader fest, wobei der Wert die HTTP-Methode der Anforderung ist. Der Server sollte mit demAccess-Control-Allow-Methods
Antwortheader antworten , wobei der Wert eine Liste der zulässigen Methoden ist.Wenn der Client das verwendet
XHR.withCredentials
, sollte der Server mit demAccess-Control-Allow-Credentials
Antwortheader mit dem Wert von antwortentrue
. Lesen Sie hier mehr .Nach alledem ist hier eine bessere Implementierung. Obwohl dies besser ist als die obige Implementierung, ist es der von mir verknüpften RESTEasy- Implementierung immer noch unterlegen , da diese Implementierung immer noch alle Ursprünge zulässt. Dieser Filter hält sich jedoch besser an die CORS-Spezifikation als der obige Filter, der nur die CORS-Antwortheader zu allen Anforderungen hinzufügt. Beachten Sie, dass Sie möglicherweise auch die ändern müssen, um sie
Access-Control-Allow-Headers
an die Header anzupassen, die Ihre Anwendung zulässt. In diesem Beispiel möchten Sie möglicherweise einige Header hinzufügen oder aus der Liste entfernen.@Provider @PreMatching public class CorsFilter implements ContainerRequestFilter, ContainerResponseFilter { /** * Method for ContainerRequestFilter. */ @Override public void filter(ContainerRequestContext request) throws IOException { // If it's a preflight request, we abort the request with // a 200 status, and the CORS headers are added in the // response filter method below. if (isPreflightRequest(request)) { request.abortWith(Response.ok().build()); return; } } /** * A preflight request is an OPTIONS request * with an Origin header. */ private static boolean isPreflightRequest(ContainerRequestContext request) { return request.getHeaderString("Origin") != null && request.getMethod().equalsIgnoreCase("OPTIONS"); } /** * Method for ContainerResponseFilter. */ @Override public void filter(ContainerRequestContext request, ContainerResponseContext response) throws IOException { // if there is no Origin header, then it is not a // cross origin request. We don't do anything. if (request.getHeaderString("Origin") == null) { return; } // If it is a preflight request, then we add all // the CORS headers here. if (isPreflightRequest(request)) { response.getHeaders().add("Access-Control-Allow-Credentials", "true"); response.getHeaders().add("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, HEAD"); response.getHeaders().add("Access-Control-Allow-Headers", // Whatever other non-standard/safe headers (see list above) // you want the client to be able to send to the server, // put it in this list. And remove the ones you don't want. "X-Requested-With, Authorization, " + "Accept-Version, Content-MD5, CSRF-Token, Content-Type"); } // Cross origin requests can be either simple requests // or preflight request. We need to add this header // to both type of requests. Only preflight requests // need the previously added headers. response.getHeaders().add("Access-Control-Allow-Origin", "*"); } }
Um mehr über CORS zu erfahren, empfehle ich, die MDN-Dokumente zu Cross-Origin Resource Sharing (CORS) zu lesen.
quelle
ResourceConfig
?Anmerkung entfernen "
@CrossOriginResourceSharing(allowAllOrigins = true)
"Dann Antwort wie folgt zurückgeben:
return Response.ok() .entity(jsonResponse) .header("Access-Control-Allow-Origin", "*") .build();
Aber das
jsonResponse
sollte durch ein POJO Objekt ersetzt werden!quelle
Die andere Antwort mag streng richtig, aber irreführend sein. Der fehlende Teil ist, dass Sie Filter aus verschiedenen Quellen miteinander mischen können. Auch wenn Jersey möglicherweise keinen CORS-Filter bietet (keine Tatsache, die ich überprüft habe, aber ich vertraue der anderen Antwort darauf), können Sie den eigenen CORS-Filter von Tomcat verwenden .
Ich benutze es erfolgreich mit Jersey. Ich habe meine eigene Implementierung des Filters für die Standardauthentifizierung, zum Beispiel zusammen mit CORS. Das Beste ist, dass der CORS-Filter in Web-XML und nicht in Code konfiguriert ist.
quelle
Um dies für mein Projekt zu lösen, habe ich Micheals Antwort verwendet und bin zu folgendem Ergebnis gekommen:
<plugin> <groupId>org.apache.tomcat.maven</groupId> <artifactId>tomcat7-maven-plugin</artifactId> <version>2.2</version> <executions> <execution> <id>run-embedded</id> <goals> <goal>run</goal> </goals> <phase>pre-integration-test</phase> <configuration> <port>${maven.tomcat.port}</port> <useSeparateTomcatClassLoader>true</useSeparateTomcatClassLoader> <contextFile>${project.basedir}/tomcat/context.xml</contextFile> <!--enable CORS for development purposes only. The web.xml file specified is a copy of the auto generated web.xml with the additional CORS filter added --> <tomcatWebXml>${maven.tomcat.web-xml.file}</tomcatWebXml> </configuration> </execution> </executions> </plugin>
Der CORS-Filter ist der grundlegende Beispielfilter von der Tomcat-Site.
Bearbeiten :
Die Variable maven.tomcat.web-xml.file ist eine pom-definierte Eigenschaft für das Projekt und enthält den Pfad zur Datei web.xml (in meinem Projekt).
quelle
Die Antwort von peeskillet ist richtig. Aber ich bekomme diesen Fehler, wenn ich die Webseite aktualisiere (sie funktioniert nur beim ersten Laden):
The 'Access-Control-Allow-Origin' header contains multiple values '*, *', but only one is allowed. Origin 'http://127.0.0.1:8080' is therefore not allowed access.
Anstatt die add-Methode zum Hinzufügen von Headern für die Antwort zu verwenden, verwende ich die put-Methode. Das ist meine Klasse
public class MCORSFilter implements ContainerResponseFilter { public static final String ACCESS_CONTROL_ALLOW_ORIGIN = "Access-Control-Allow-Origin"; public static final String ACCESS_CONTROL_ALLOW_ORIGIN_VALUE = "*"; private static final String ACCESS_CONTROL_ALLOW_CREDENTIALS = "Access-Control-Allow-Credentials"; private static final String ACCESS_CONTROL_ALLOW_CREDENTIALS_VALUE = "true"; public static final String ACCESS_CONTROL_ALLOW_HEADERS = "Access-Control-Allow-Headers"; public static final String ACCESS_CONTROL_ALLOW_HEADERS_VALUE = "Cache-Control, Pragma, Origin, Authorization, Content-Type, X-Requested-With, Accept"; public static final String ACCESS_CONTROL_ALLOW_METHODS = "Access-Control-Allow-Methods"; public static final String ACCESS_CONTROL_ALLOW_METHODS_VALUE = "GET, POST, PUT, DELETE, OPTIONS, HEAD"; public static final String[] ALL_HEADERs = { ACCESS_CONTROL_ALLOW_ORIGIN, ACCESS_CONTROL_ALLOW_CREDENTIALS, ACCESS_CONTROL_ALLOW_HEADERS, ACCESS_CONTROL_ALLOW_METHODS }; public static final String[] ALL_HEADER_VALUEs = { ACCESS_CONTROL_ALLOW_ORIGIN_VALUE, ACCESS_CONTROL_ALLOW_CREDENTIALS_VALUE, ACCESS_CONTROL_ALLOW_HEADERS_VALUE, ACCESS_CONTROL_ALLOW_METHODS_VALUE }; @Override public ContainerResponse filter(ContainerRequest request, ContainerResponse response) { for (int i = 0; i < ALL_HEADERs.length; i++) { ArrayList<Object> value = new ArrayList<>(); value.add(ALL_HEADER_VALUEs[i]); response.getHttpHeaders().put(ALL_HEADERs[i], value); //using put method } return response; } }
Fügen Sie diese Klasse zu init-param in der Datei web.xml hinzu
quelle