Как включить Междоменные запросы на веб-службах JAX-RS?
Я разработал набор веб-сервисов restful. Я не мог вызвать ни один из этих методов из удаленных клиентов из-за ошибки
No 'Access-Control-Allow-Origin' header is present on the requested resource.
сервисы отлично работают на localhost. Есть ли какие-либо изменения или конфиги на сервер чтобы решить эту проблему. т. е. включить междоменные запросы.
Я использую WildFly 8, JavaEE 7
8 ответов:
мне было интересно то же самое, поэтому после небольшого исследования я обнаружил, что самый простой способ-просто использовать JAX-RS
ContainerResponseFilter
для добавления соответствующих заголовков CORS. Таким образом, вам не нужно заменять весь стек веб-сервисов на CXF (Wildfly использует CXF в какой-то форме, но не похоже, что он использует его для JAX-RS, возможно, только JAX-WS).независимо от того, используете ли вы этот фильтр, он добавит заголовки к каждому веб-сервису 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"); } }
потом, когда я тестировал с curl, в ответе были заголовки 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
Я так понимаю, что это
@Provider
аннотация, которая сообщает среде выполнения JAX-RS использовать фильтр, без аннотации ничего не происходит.у меня есть идея об использовании
ContainerResponseFilter
С пример-Джерси.
я столкнулся с аналогичной проблемой, и попытался использовать @Alex Petty's решение, но помимо того, чтобы установить заголовки CORS на каждой конечной точке JAX-RS в моем классе, как таковой:
@GET @Produces(MediaType.APPLICATION_JSON) public Response getMemberList() { List<Member> 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(); }
мне пришлось дополнительно определить уловку
OPTIONS
конечная точка, которая будет возвращать заголовки CORS для любого другогоOPTIONS
запрос в классе, и таким образом поймать все точки вида:@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(); }
только после этого я мог бы правильно использовать свои конечные точки API JAX-RS от Клиенты jQuery Ajax на других доменах или хостах.
Я нашел еще более простой (RestEasy-specific) способ включить CORS на Wildfly без использования фильтра и где вы можете управлять конфигурацией заголовка ответа API на уровне ресурсов.
например:
@GET @Produces(MediaType.APPLICATION_JSON) public Response getMemberList() { List<Member> 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(); }
мне повезло настроить общий доступ к ресурсам Cross-origin (CORS) для моего API (на Wildfly) с помощью этой библиотеки:
<dependency> <groupId>com.thetransactioncompany</groupId> <artifactId>cors-filter</artifactId> <version>2.1</version> </dependency>
это очень легко настроить. Просто добавьте вышеуказанную зависимость в свой pom, а затем добавьте следующую конфигурацию в раздел webapp вашего интернета.XML-файл.
<filter> <filter-name>CORS</filter-name> <filter-class>com.thetransactioncompany.cors.CORSFilter</filter-class> <init-param> <param-name>cors.allowGenericHttpRequests</param-name> <param-value>true</param-value> </init-param> <init-param> <param-name>cors.allowOrigin</param-name> <param-value>*</param-value> </init-param> <init-param> <param-name>cors.allowSubdomains</param-name> <param-value>false</param-value> </init-param> <init-param> <param-name>cors.supportedMethods</param-name> <param-value>GET, HEAD, POST, DELETE, OPTIONS</param-value> </init-param> <init-param> <param-name>cors.supportedHeaders</param-name> <param-value>*</param-value> </init-param> <init-param> <param-name>cors.supportsCredentials</param-name> <param-value>true</param-value> </init-param> <init-param> <param-name>cors.maxAge</param-name> <param-value>3600</param-value> </init-param> </filter> <filter-mapping> <!-- CORS Filter mapping --> <filter-name>CORS</filter-name> <url-pattern>*</url-pattern> </filter-mapping>
вы также можете настроить его с помощью файла свойств, если вы предпочитаете. Эта библиотека работает как шарм и дает вам много гибкости конфигурации!
ни один из других ответов не работал для меня, но это было:
import javax.ws.rs.core.Response;
затем измените тип возврата метода службы на
Response
, и изменитьreturn
заявление:return Response.ok(resp).header("Access-Control-Allow-Origin", "*").build();
здесь
resp
является исходным объектом ответа.
можно использовать
javax.ws.rs.core.Feature
как показано ниже для реализации 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; } }
просто чтобы добавить что-то к другим ответам. Разрешение * немного опасно. Что можно сделать, так это настроить базу данных разрешенного происхождения (это может быть файл)
затем, когда запрос прибудет вы можете сделать:
// 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, <HERE PUT YOUR DEDICATED HEADERS>); 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"); }
таким образом, вы не позволите всем.
@Joel Pearson ответ помог, но для кого-то, кто новичок в JAX-RS, как я, и запускает службу на tomcat, настроив web.xml должен быть осторожным при создании класса и размещении его в любом месте проекта. См. пакет, указанный в разделе для Джерси, и создайте там этот класс фильтра. Таким образом, это сработало для меня.