Hinweis: Lesen Sie unbedingt das UPDATE unten
@CrossOriginResourceSharing
ist eine CXF-Anmerkung, daher funktioniert sie mit Jersey nicht.
Bei Jersey verwende ich normalerweise nur a, um mit CORS umzugehen ContainerResponseFilter
. Die ContainerResponseFilter
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 der ResourceConfig
oder der Application
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);
Wenn Sie für Jersey 2.x Probleme beim Registrieren dieses Filters haben, finden Sie hier einige Ressourcen, die möglicherweise hilfreich sind
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
<init-param>
<param-name>com.sun.jersey.spi.container.ContainerResponseFilters</param-name>
<param-value>com.yourpackage.CORSFilter</param-value>
</init-param>
Oder ResourceConfig
du kannst es tun
resourceConfig.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üfenCorsFilter
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 den Access-Control-Allow-Origin
Header enthält, und gibt an, dass der Ursprung des Origin
Headers zulässig ist. Damit es als "einfache Anfrage" betrachtet werden kann, muss es die folgenden Kriterien erfüllen:
- Seien Sie eine der folgenden Methoden:
- Abgesehen von den vom Browser automatisch festgelegten Headern enthält die Anforderung möglicherweise nur die folgenden manuell festgelegten Header:
Accept
Accept-Language
Content-Language
Content-Type
DPR
Save-Data
Viewport-Width
Width
- Die einzigen zulässigen Werte für den
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:
Preflight Request and Response Headers
+-----------------------------------+--------------------------------------+
| REQUEST HEADER | RESPONSE HEADER |
+===================================+======================================+
| Origin | Access-Control-Allow-Origin |
+-----------------------------------+--------------------------------------+
| Access-Control-Request-Headers | Access-Control-Allow-Headers |
+-----------------------------------+--------------------------------------+
| Access-Control-Request-Method | Access-Control-Allow-Methods |
+-----------------------------------+--------------------------------------+
| XHR.withCredentials | Access-Control-Allow-Credentials |
+-----------------------------------+--------------------------------------+
Mit dem Origin
Anforderungsheader ist der Wert die Ursprungsserverdomäne, und die Antwort Access-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 einem Access-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 dem Access-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 dem Access-Control-Allow-Credentials
Antwortheader mit dem Wert von antworten true
. 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 {
@Override
public void filter(ContainerRequestContext request) throws IOException {
if (isPreflightRequest(request)) {
request.abortWith(Response.ok().build());
return;
}
}
private static boolean isPreflightRequest(ContainerRequestContext request) {
return request.getHeaderString("Origin") != null
&& request.getMethod().equalsIgnoreCase("OPTIONS");
}
@Override
public void filter(ContainerRequestContext request, ContainerResponseContext response)
throws IOException {
if (request.getHeaderString("Origin") == null) {
return;
}
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",
"X-Requested-With, Authorization, " +
"Accept-Version, Content-MD5, CSRF-Token, Content-Type");
}
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.