如何在JAX-RS Web服务上启用跨域请求?

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

这些服务在localhost上完美运行。 是否有任何更改或configuration在服务器端来解决问题。 即启用跨域请求。

我正在使用WildFly 8,JavaEE 7

我想知道同样的事情,所以经过一番研究,我发现最简单的方法就是使用JAX-RS ContainerResponseFilter来添加相关的CORS头文件。 这样你就不需要用CXF来replace整个Web服务栈(Wildfly使用CXF是某种forms,但是它看起来并不像JAX-RS使用它,也许只有JAX-WS)。

无论你使用这个filter,它都会把标题添加到每个REST webservice。

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

然后当我用curltesting时,响应有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运行时使用filter,没有注释没有任何反应。

我想到了使用Jersey例子中的ContainerResponseFilter的想法。

我遇到了一个类似的问题,并试图使用@Alex Petty的解决scheme ,但除了必须在我的类中的每个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头文件,从而捕获所有types的端点:

 @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端点。

我发现了一个更简单(RestEasy特定)的方式来启用Wildfly上的CORS,而不使用filter,并且可以在资源级别控制API响应头configuration。

例如:

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

我有幸使用这个lib为我的API(Wildfly)configuration了跨源资源共享(CORS):

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

这是很容易安装。 只需将上面的依赖项添加到您的pom中,然后将以下configuration添加到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> 

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

没有其他的答案为我工作,但这样做:

import javax.ws.rs.core.Response;

然后将服务方法的返回types更改为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; } } 

只是为了添加其他答案。 允许*有点危险。 可以做什么是configuration一个允许的来源数据库(它可以是一个文件)

然后当请求到达时,你可以做:

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

那样你就不会容许每个人。