Подтвердить что ты не робот

Как включить запросы перекрестных доменов на веб-сервисы JAX-RS?

Я разработал набор успокаивающих веб-сервисов. Я не мог назвать любой из этих методов удаленными клиентами из-за ошибки No 'Access-Control-Allow-Origin' header is present on the requested resource.

Услуги отлично работают на localhost. Существуют ли какие-либо изменения или настройки на стороне сервера , чтобы решить проблему. то есть разрешить запросы с кросс-доменами.

Я использую WildFly 8, JavaEE 7

4b9b3361

Ответ 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, следует быть осторожным при создании класса и размещении его в любом месте проекта. Посмотрите пакет, который вы указали в разделе для джерси, и создайте там этот класс фильтра. Таким образом, это сработало для меня.