75

我开发了一套宁静的网络服务。由于错误,我无法从远程客户端调用任何这些方法 No 'Access-Control-Allow-Origin' header is present on the requested resource.

这些服务在本地主机上完美运行。在服务器端是否有任何更改或配置可以解决问题。即启用跨域请求。

我正在使用 WildFly 8、JavaEE 7

4

9 回答 9

117

我想知道同样的事情,所以经过一番研究后,我发现最简单的方法就是使用 JAX-RSContainerResponseFilter添加相关的 CORS 标头。这样您就不需要用 CXF 替换整个 Web 服务堆栈(Wildfly 使用 CXF 是某种形式,但它看起来不像将它用于 JAX-RS 可能只有 JAX-WS)。

无论您是否使用此过滤器,它都会将标头添加到每个 REST Web 服务。

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 运行时使用过滤器,没有注释什么都不会发生。

我得到了使用ContainerResponseFilterfrom a Jersey example的想法。

于 2014-05-13T12:37:08.983 回答
19

我遇到了类似的问题,并尝试使用@Alex Petty 的解决方案,但除了必须在我的班级中的每个 JAX-RS 端点上设置 CORS 标头之外,如下所示:

@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的任何其他OPTIONS请求返回 CORS 标头,从而捕获排序的所有端点:

@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();
}

只有在这样做之后,我才能在其他域或主机上正确使用来自 Jquery Ajax 客户端的 JAX-RS API 端点。

于 2015-03-11T20:16:13.867 回答
12

我发现了一种更简单(RestEasy 特定)的方法来在 Wildfly 上启用 CORS,而无需使用过滤器,并且您可以在资源级别控制 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();
}
于 2014-08-08T15:03:41.920 回答
11

通过使用这个库,我很幸运地为我的 API(在 Wildfly 上)配置了跨域资源共享 (CORS):

<dependency>
<groupId>com.thetransactioncompany</groupId>
<artifactId>cors-filter</artifactId>
<version>2.1</version>
</dependency>

设置非常简单。只需将上述依赖项添加到您的 pom 中,然后将以下配置添加到您的 web.xml 文件的 webapp 部分。

<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>

如果您愿意,也可以使用属性文件对其进行配置。这个库就像一个魅力,给你很大的配置灵活性!

于 2014-06-27T04:43:09.820 回答
7

其他答案都不适合我,但这确实:

import javax.ws.rs.core.Response;

然后将服务方法的返回类型更改为Response,并将return语句更改为:

return Response.ok(resp).header("Access-Control-Allow-Origin", "*").build();

resp原始响应对象在哪里。

于 2015-07-18T15:47:47.777 回答
4

您也可以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;
 }

}
于 2016-12-06T11:47:56.090 回答
2

解决方案在响应中添加了一些标头。在 spring 或 spring boot 中有注释,但在旧系统中,可能没有注释。您可以通过添加过滤器来解决。

过滤器类:

package com.koushik.restapis.intercepter;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;


public class RestCorsFilter implements Filter {

    @Override
    public void destroy() {
    enter code here
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
    
        HttpServletResponse resp = (HttpServletResponse) response;
        resp.addHeader("Access-Control-Allow-Origin", "*");
        resp.addHeader("Access-Control-Allow-Headers", "*");
        resp.addHeader("Access-Control-Allow-Methods", "*");
        
        chain.doFilter(request, resp);
        
    }

    @Override
    public void init(FilterConfig arg0) throws ServletException {
        
    }

}

web.xml

  <filter>
    <filter-name>RestCorsFilter</filter-name>
    <filter-class>com.koushik.restapis.RestCorsFilter</filter-class>
  </filter>
    <filter-mapping>
    <filter-name>RestCorsFilter</filter-name>
    <url-pattern>/apis/*</url-pattern>
  </filter-mapping>
于 2020-09-05T11:07:26.400 回答
0

@Joel Pearson 的回答有所帮助,但对于像我这样的 JAX-RS 新手并通过配置 web.xml 在 tomcat 上运行服务的人来说,在创建类并将其放在项目中的任何位置时应该小心。请参阅您在下面为 jersey 指定的包并在那里创建此过滤器类。这样它对我有用。

于 2018-09-14T15:43:32.887 回答
0

只是为其他回复添加一些内容。允许 * 有点危险。可以做的是配置允许来源的数据库(可以是文件)

然后,当请求到达时,您可以执行以下操作:

// 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");
}

这样你就不会允许所有人。

于 2017-06-05T11:55:01.847 回答