5

我有两台服务器(Apache 和 JBoss AS7),我需要向客户端提供对所有 http 方法的访问。所有这些请求都必须通过 ajax 发送。客户端代码示例:

$.ajax({
      type: "get",
      url: "http://localhost:9080/myproject/services/mobile/list",
      crossDomain: true,
      cache: false,
      dataType: "json",
      success: function(response) {
        console.log(response);
      },
      error: function (jqXHR, textStatus, errorThrown) {
        console.log(textStatus);
        console.log(jqXHR.responseText);
        console.log(errorThrown);
        }
    });

在 JBoss AS7 中,我使用的是 RESTEasy,实现 CORS 如下:

@Path("/mobile")
@Provider
@ServerInterceptor
public class GroupMobile implements MessageBodyWriterInterceptor {

@Inject
private GroupDAO groupDAO;

@GET
@Path("/list")
@Produces(MediaType.APPLICATION_JSON)
public List<Group> getGroups() {
    return groupDAO.listAll();
}

@Override
public void write(MessageBodyWriterContext context) throws IOException,
        WebApplicationException {
    context.getHeaders().add("Access-Control-Allow-Origin", "*");
    context.proceed();
}

@OPTIONS
@Path("/{path:.*}")
public Response handleCORSRequest(
        @HeaderParam("Access-Control-Request-Method") final String requestMethod,
        @HeaderParam("Access-Control-Request-Headers") final String requestHeaders) {
    final ResponseBuilder retValue = Response.ok();

    if (requestHeaders != null)
        retValue.header("Access-Control-Allow-Headers", requestHeaders);

    if (requestMethod != null)
        retValue.header("Access-Control-Allow-Methods", requestMethod);

    retValue.header("Access-Control-Allow-Origin", "*");

    return retValue.build();
}
}

web.xml 和 beans.xml 是空文件。当我访问 MyIP:8080 (Apache) 时,我收到错误消息:

XMLHttpRequest cannot load http://localhost:9080/myproject/services/mobile/list?_=1359480354190. Origin http://MyIP:8080 is not allowed by Access-Control-Allow-Origin.

有人知道出了什么问题吗?

4

5 回答 5

11

最新的 resteasy (3.0.9-Final) 包括一个实用程序类org.jboss.resteasy.plugins.interceptors.CorsFilter

您可以将 CorsFilter 对象添加到 Application 的单例对象集中,也可以直接将其添加到 ResteasyDeployment 的 ProviderFactory 中。

以下是示例应用程序类:

import java.util.HashSet;
import java.util.Set;
import javax.ws.rs.ApplicationPath;

import org.jboss.resteasy.plugins.interceptors.CorsFilter;


@ApplicationPath("/api")
public class RestApplication extends javax.ws.rs.core.Application {
    Set<Object> singletons;

    @Override
    public Set<Class<?>> getClasses() {
        HashSet<Class<?>> clazzes = new HashSet<>();
        clazzes.add(VersionService.class);
        return clazzes;
    }

    @Override
    public Set<Object> getSingletons() {
        if (singletons == null) {
            CorsFilter corsFilter = new CorsFilter();
            corsFilter.getAllowedOrigins().add("*");

            singletons = new LinkedHashSet<Object>();
            singletons.add(corsFilter);
        }
        return singletons;
    }
}
于 2015-03-21T15:24:17.723 回答
1

听起来这个问题与https://issues.jboss.org/browse/RESTEASY-878有关。您可能无法使用MessageBodyWriterInterceptor. 尝试改用 servlet 过滤器 ( @WebFilter)。

于 2013-12-26T13:20:16.303 回答
1

您遇到的问题是您正在尝试执行跨站点脚本。您访问了该页面,http://MyIP:8080因此浏览器阻止您访问该域之外的资源。这是非常特定于浏览器的,基于浏览器的解决方法都会有所不同(您可以全局禁用 Chrome 中的安全性,也可以在 IE 中基于每个站点禁用安全性)。

如果您将页面加载为http://localhost:8080,则它应该允许您访问查询。或者,您可以实现将转发请求的代理。

于 2013-01-29T18:09:38.250 回答
1

好吧,我已经实现了一个小解决方案,首先我在我的项目 Web 中做了一个拦截器,我创建了一个名为“CORSInterceptor”的类,该类就是这种方式。

import org.jboss.resteasy.annotations.interception.ServerInterceptor;
import org.jboss.resteasy.core.ResourceMethod;
import org.jboss.resteasy.core.ServerResponse;
import org.jboss.resteasy.spi.Failure;
import org.jboss.resteasy.spi.HttpRequest;
import org.jboss.resteasy.spi.interception.MessageBodyWriterContext;
import org.jboss.resteasy.spi.interception.MessageBodyWriterInterceptor;
import org.jboss.resteasy.spi.interception.PreProcessInterceptor;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.ext.Provider;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

@Provider
@ServerInterceptor
public class CorsInterceptor implements PreProcessInterceptor, MessageBodyWriterInterceptor {

/**
     * The Origin header set by the browser at each request.
     */
    private static final String ORIGIN = "Origin";


 /**
     * The Access-Control-Allow-Origin header indicates which origin a resource it is specified for can be
     * shared with. ABNF: Access-Control-Allow-Origin = "Access-Control-Allow-Origin" ":" source origin string | "*"
     */
    private static final String ACCESS_CONTROL_ALLOW_ORIGIN = "Access-Control-Allow-Origin";


   //
    private static final ThreadLocal<String> REQUEST_ORIGIN = new ThreadLocal<String>();
    //
    private final Set<String> allowedOrigins;


 public CorsInterceptor(){
   this.allowedOrigins = new HashSet<String>();
   this.allowedOrigins.add("*");
 }

   @Override
    public ServerResponse preProcess(HttpRequest request, ResourceMethod method) throws Failure, WebApplicationException {
        if (!allowedOrigins.isEmpty()) {
            REQUEST_ORIGIN.set(request.getHttpHeaders().getRequestHeaders().getFirst(ORIGIN));
        }
        return null;
    }


@Override
public void write(MessageBodyWriterContext context) throws IOException, WebApplicationException {
    if (!allowedOrigins.isEmpty() && (allowedOrigins.contains(REQUEST_ORIGIN.get()) || allowedOrigins.contains("*"))) {
        context.getHeaders().add(ACCESS_CONTROL_ALLOW_ORIGIN, REQUEST_ORIGIN.get());
      }
    context.proceed();
    }
}

在 File Web.xml中,我添加它

<context-param>
    <param-name>resteasy.providers</param-name>
    <param-value><package>.CorsInterceptor</param-value>
</context-param>

package : 类的 Ubication。

请求我使用过的 JQuery。

$.ajax({
    type: 'GET',
    dataType: "json", 

    crossDomain : true,

    cache:false, 
    url: "http://localhost:12005/ProyectoWebServices/ws/servicioTest",
    success: function (responseData, textStatus, jqXHR) {
       alert("Successfull: "+responseData);
    },
    error: function (responseData, textStatus, errorThrown) {
        alert("Failed: "+responseData);
    }
});

它对我来说很好。我希望它可以帮助你。

于 2014-07-24T05:06:30.197 回答
0

我最近遇到了同样的问题并添加了对我有用的解决方案:

以下是我所做的:

  • 我创建了一个扩展 javax.ws.rs.core.Application 的类,并向其中添加了一个 Cors 过滤器。

在 CORS 过滤器中,我添加了corsFilter.getAllowedOrigins().add("http://localhost:4200");.

基本上,您应该添加要允许跨域资源共享的 URL。Ans 您也可以使用"*"而不是任何特定的 URL 来允许任何 URL。

public class RestApplication
    extends Application
{
    private Set<Object> singletons = new HashSet<Object>();

    public MessageApplication()
    {
        singletons.add(new CalculatorService()); //CalculatorService is your specific service you want to add/use.
        CorsFilter corsFilter = new CorsFilter();
        // To allow all origins for CORS add following, otherwise add only specific urls.
        // corsFilter.getAllowedOrigins().add("*");
        System.out.println("To only allow restrcited urls ");
        corsFilter.getAllowedOrigins().add("http://localhost:4200");
        singletons = new LinkedHashSet<Object>();
        singletons.add(corsFilter);
    }

    @Override
    public Set<Object> getSingletons()
    {
        return singletons;
    }
}
  • 这是我的 web.xml:
<web-app id="WebApp_ID" version="2.4"
    xmlns="http://java.sun.com/xml/ns/j2ee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee 
    http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
    <display-name>Restful Web Application</display-name>

    <!-- Auto scan rest service -->
    <context-param>
        <param-name>resteasy.scan</param-name>
        <param-value>true</param-value>
    </context-param>

    <context-param>
        <param-name>resteasy.servlet.mapping.prefix</param-name>
        <param-value>/rest</param-value>
    </context-param>

    <listener>
        <listener-class>
            org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap
        </listener-class>
    </listener>

    <servlet>
        <servlet-name>resteasy-servlet</servlet-name>
        <servlet-class>
            org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher
        </servlet-class>
        <init-param>
            <param-name>javax.ws.rs.Application</param-name>
            <param-value>com.app.RestApplication</param-value>
        </init-param>
    </servlet>

    <servlet-mapping>
        <servlet-name>resteasy-servlet</servlet-name>
        <url-pattern>/rest/*</url-pattern>
    </servlet-mapping>

</web-app>

有一些您可能不需要或更改的自定义更改,例如:

    <servlet-mapping>
        <servlet-name>resteasy-servlet</servlet-name>
        <url-pattern>/rest/*</url-pattern>
    </servlet-mapping>

或者

    <context-param>
        <param-name>resteasy.scan</param-name>
        <param-value>true</param-value>
    </context-param>

或者

    <context-param>
        <param-name>resteasy.servlet.mapping.prefix</param-name>
        <param-value>/rest</param-value>
    </context-param>

当我遇到这个问题时,我缺少 的最重要的代码是,我没有将我的类扩展 javax.ws.rs.Application 即 RestApplication 添加到 init-param<servlet-name>resteasy-servlet</servlet-name>

   <init-param>
        <param-name>javax.ws.rs.Application</param-name>
        <param-value>com.app.RestApplication</param-value>
    </init-param>

因此我的过滤器无法执行,因此应用程序不允许来自指定 URL 的 CORS。

PS:我使用的是 RestEasy 版本:3.12.1.Final

于 2020-07-18T12:06:10.027 回答