问题
I developed a set of restful web services. I couldn\'t call any of these methods from remote clients due to the error
No \'Access-Control-Allow-Origin\' header is present on the requested resource.
The services work perfectly on localhost. Is there any changes or configs to do on the server side to resolve the issue. i.e. to enable cross domain requests.
I\'m using WildFly 8, JavaEE 7
回答1:
I was wondering the same thing, so after a bit of research I found that the easiest way was simply to use a JAX-RS ContainerResponseFilter
to add the relevant CORS headers. This way you don't need to replace the whole web services stack with CXF (Wildfly uses CXF is some form, but it doesn't look like it uses it for JAX-RS maybe only JAX-WS).
Regardless if you use this filter it will add the headers to every 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");
}
}
Then when I tested with curl, the response had the CORS headers:
$ 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
My understanding is that it's the @Provider
annotation that tells the JAX-RS runtime to use the filter, without the annotation nothing happens.
I got the idea about using the ContainerResponseFilter
from a Jersey example.
回答2:
I was facing a similar problem, and had tried to use @Alex Petty's solution, but apart from having to set the CORS headers on each JAX-RS endpoint in my class, as such:
@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();
}
I had to further define a catch-all OPTIONS
endpoint that would return the CORS headers for any other OPTIONS
request in the class, and thus catch all endpoint of the sort:
@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();
}
Only after doing this, could I properly use my JAX-RS API endpoints from Jquery Ajax clients on other domains or hosts.
回答3:
I found an even easier (RestEasy-specific) way to enable CORS on Wildfly without using a filter and where you can control your APIs response header configuration at the resource level.
For example:
@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:
I have had good luck configuring Cross-origin resource sharing (CORS) for my API (on Wildfly) by using this lib:
<dependency>
<groupId>com.thetransactioncompany</groupId>
<artifactId>cors-filter</artifactId>
<version>2.1</version>
</dependency>
It's very easy to setup. Just add the above dependency to your pom and then add the following config to the webapp section of your web.xml file.
<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>
You can also configure it with a properties file instead if you prefer. This lib works like a charm and gives you a lot of configuration flexibility!
回答5:
None of the other answers worked for me, but this did:
import javax.ws.rs.core.Response;
Then change the return type of the service method to Response
, and change the return
statement to:
return Response.ok(resp).header("Access-Control-Allow-Origin", "*").build();
Where resp
is the original response object.
回答6:
You can also implement javax.ws.rs.core.Feature
as below to implement 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:
Just to add something to other responses. Allowing * is a little bit dangerous. What can be done is configuring a database of the allowed origin (it can be a file)
Then when the request arrive you can do:
// 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");
}
In that way you won't allow everyone.
回答8:
@Joel Pearson answer helped but for someone who is new to JAX-RS like me and is running the service on tomcat by configuring web.xml should be careful while creating the class and putting it anywhere in the project. See the package you specified in under for jersey and create this filter class there. That way it worked for me.
来源:https://stackoverflow.com/questions/23450494/how-to-enable-cross-domain-requests-on-jax-rs-web-services