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



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

服务在本地主机上运行良好。在服务器端上是否有任何更改或配置来解决此问题?即启用跨域请求。

我使用的是WildFly 8, JavaEE 7

我也想知道同样的事情,所以经过一些研究后,我发现最简单的方法就是使用JAX-RS ContainerResponseFilter来添加相关的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运行时使用过滤器,没有注释什么都不会发生。

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

我面临着类似的问题,并尝试使用@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端点。

我发现了一种更简单(特定于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();
}

我很幸运地通过使用这个库为我的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>

如果您愿意,也可以使用属性文件来配置它。这个库工作起来很有魅力,为您提供了很多配置灵活性!

其他答案都不适合我,但这个答案管用:

import javax.ws.rs.core.Response;

修改服务方法的返回类型为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;
 }
}

解决方案是在响应中添加一些头。在spring或spring引导中有注解,但在旧的系统中,可能没有注解。你可以通过添加一个过滤器来解决。

过滤器类:

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>

@Joel Pearson的回答很有帮助,但是对于像我这样刚接触JAX-RS并且通过配置web.xml在tomcat上运行服务的人来说,在创建类并将其放在项目中的任何地方时应该小心。请参阅您在jersey中指定的包,并在其中创建此筛选器类。

只是为了给其他回复添加一些东西。允许*有点危险。可以做的是配置允许的源数据库(它可以是一个文件)

当请求到达时,你可以这样做:

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

这样你就不会让每个人。

我最近遇到了这个问题并解决了它,但基本上创建了一个过滤器,实现了ContainerResponseFilter并添加了CORS头,如下所示:

@Override
    public void filter(ContainerRequestContext containerRequestContext, ContainerResponseContext containerResponseContext) throws IOException {
        containerResponseContext.getHeaders().add(
                "Access-Control-Allow-Origin", "*");
        containerResponseContext.getHeaders().add(
                "Access-Control-Allow-Credentials", "true");
        containerResponseContext.getHeaders().add(
                "Access-Control-Allow-Headers",
                "origin, content-type, accept, authorization");
        containerResponseContext.getHeaders().add(
                "Access-Control-Allow-Methods",
                "GET, POST, PUT, DELETE, OPTIONS, HEAD");
    }

因为您使用的是JAX-RS,所以您的应用程序类扩展了Applicaton类,您只需要重写它的getsingleton方法:

@Override
public Set<Object> getSingletons() {
        return mySingletons();
    }

,你的单例可以如下:

public static Set<Object> mySingletons() {
        Set<Object> singletons = new HashSet<>();
        singletons.add(new MyFilter());
        return singletons;
    }

我尝试了上面的答案与web.xml等的变化,没有一个工作,所以我想出了这个解决方案,尝试了一切。

相关内容

  • 没有找到相关文章

最新更新