Как включить запросы перекрестных доменов на веб-сервисы JAX-RS?
Я разработал набор успокаивающих веб-сервисов. Я не мог назвать любой из этих методов удаленными клиентами из-за ошибки
No 'Access-Control-Allow-Origin' header is present on the requested resource.
Услуги отлично работают на localhost. Существуют ли какие-либо изменения или настройки на стороне сервера , чтобы решить проблему. то есть разрешить запросы с кросс-доменами.
Я использую WildFly 8, JavaEE 7
Ответы
Ответ 1
Мне было интересно то же самое, поэтому после небольшого исследования я обнаружил, что самым простым способом было просто использовать 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
из Пример Джерси.
Ответ 2
Я столкнулся с аналогичной проблемой и попытался использовать @Alex Petty решение, но помимо необходимости устанавливать заголовки 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();
}
Мне пришлось дополнительно определить конечную точку catch-all 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 на других доменах или хостах.
Ответ 3
Я нашел еще более простой способ (RestEasy) включить CORS на Wildfly без использования фильтра и где вы можете управлять конфигурацией заголовка ответа API 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();
}
Ответ 4
Мне посчастливилось настроить совместное использование ресурсов Cross-origin (CORS) для моего API (на Wildfly), используя этот lib:
<dependency>
<groupId>com.thetransactioncompany</groupId>
<artifactId>cors-filter</artifactId>
<version>2.1</version>
</dependency>
Это очень просто настроить. Просто добавьте вышеуказанную зависимость к вашему pom, а затем добавьте следующую конфигурацию в раздел webapp вашего файла web.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>
Вы также можете настроить его с помощью файла свойств, если хотите. Эта библиотека работает как шарм и дает вам большую гибкость в настройке!
Ответ 5
Ни один из других ответов не работал у меня, но это делало:
import javax.ws.rs.core.Response;
Затем измените тип возврата метода службы на Response
и измените оператор return
на:
return Response.ok(resp).header("Access-Control-Allow-Origin", "*").build();
Где resp
- исходный объект ответа.
Ответ 6
Вы также можете реализовать 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;
}
}
Ответ 7
Просто чтобы добавить что-то к другим ответам.
Разрешить * немного опасно.
Что можно сделать, это настроить базу данных разрешенного источника (это может быть файл)
Затем, когда запрос поступит, вы можете сделать:
// 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");
}
Таким образом, вы не разрешите всем.
Ответ 8
Ответ @Joel Pearson помог, но для тех, кто является новичком в JAX-RS, таких как я, и запускает службу на tomcat путем настройки web.xml, следует быть осторожным при создании класса и размещении его в любом месте проекта. Посмотрите пакет, который вы указали в разделе для джерси, и создайте там этот класс фильтра. Таким образом, это сработало для меня.