问题
I have two servers (Apache and JBoss AS7) and I need to provide access to all http methods to a client. All these request must be sent via ajax. Example of the client code:
$.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);
}
});
In JBoss AS7 I'm using RESTEasy, implementing CORS as follows:
@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 and beans.xml are empty files. When I access MyIP:8080 (Apache), I get the error message:
XMLHttpRequest cannot load http://localhost:9080/myproject/services/mobile/list?_=1359480354190. Origin http://MyIP:8080 is not allowed by Access-Control-Allow-Origin.
Does anybody know what is wrong?
回答1:
The problem you are having is your are trying to do cross-site scripting. You accessed the page at http://MyIP:8080
and so the browser is preventing you from accessing resources outside that domain. This is very browser specific and browser based work arounds will all be different (you can disable security in Chrome globally, and on a per site basis in IE).
If you load the page as http://localhost:8080
, it should then allow you access the query. Alternatively, you can implement a proxy which will forward the request.
回答2:
The newest resteasy (3.0.9-Final) include a utility class org.jboss.resteasy.plugins.interceptors.CorsFilter
.
You can add the CorsFilter object into Application's singleton objects set, or add it into ProviderFactory in ResteasyDeployment directly.
The following is the sample application class:
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;
}
}
回答3:
Sounds like the issue is related to https://issues.jboss.org/browse/RESTEASY-878. You may not be able to catch CORS preflight requests with MessageBodyWriterInterceptor
. Try using servlet filters (@WebFilter
) instead.
回答4:
Well, I have implemented a small solution, first I do a interceptor in my project Web I created a class called "CORSInterceptor" the class is of the way.
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();
}
}
In the File Web.xml, I add it
<context-param>
<param-name>resteasy.providers</param-name>
<param-value><package>.CorsInterceptor</param-value>
</context-param>
package: Ubication of the class.
Request JQuery that I have used.
$.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);
}
});
it worked fine for me. I hope that it can help you.
来源:https://stackoverflow.com/questions/14589031/ajax-request-with-jax-rs-resteasy-implementing-cors