CORS in JAX-RS – CORS和JAX-RS

最后修改: 2017年 3月 27日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

In this quick article, we’ll learn about how to enable CORS (Cross-Origin Resource Sharing) in a JAX-RS based system. We’ll set up an application on top of JAX-RS to enable CORS mechanism.

在这篇文章中,我们将了解如何在基于JAX-RS的系统中启用CORS跨源资源共享)。我们将在JAX-RS之上设置一个应用程序,以启用CORS机制。

2. How to Enable CORS Mechanism

2.如何启用CORS机制

There are two ways by which we can enable CORS in JAX-RS. The first and the most basic way is to create a filter to inject necessary response header at run-time in every request. The other one is to manually add an appropriate header in each URL endpoint.

我们有两种方法可以在 JAX-RS 中启用 CORS。第一个也是最基本的方法是创建一个过滤器,在每个请求的运行时注入必要的响应头。另一种是在每个 URL 端点中手动添加一个适当的头。

Ideally, the first solution should be used; however, when that’s not an option, the more manual option is technical OK as well.

理想情况下,应该使用第一个解决方案;然而,当这不是一个选项时,更多的手动选项在技术上也是可以的。

2.1. Using the Filter

2.1.使用过滤器

JAX-RS has the ContainerResponseFilter interface – implemented by the container response filters. Typically, this filter instance is applied globally to any HTTP response.

JAX-RSContainerResponseFilter接口 – 由容器响应过滤器实现。通常情况下,这个过滤器实例被全局地应用于任何 HTTP 响应。

We’ll implement this interface to create a custom filter which will inject Access-Control-Allow-* header to each outgoing request and enable the CORS mechanism:

我们将实现这个接口来创建一个自定义过滤器,它将向每个发出的请求注入Access-Control-Allow-*头并启用CORS机制。

@Provider
public class CorsFilter implements ContainerResponseFilter {

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

A couple of points here:

这里有几个要点。

  • Filters implementing ContainerResponseFilter must be explicitly annotated with @Provider to be discovered by the JAX-RS runtime
  • We’re injecting ‘Access-Control-Allow-*‘ header with ‘*’, that means any URL endpoints to this server instance can be accessed via any domain; if we want to restrict the cross-domain access explicitly, we have to mention that domain in this header

2.2. Using Header Modification into Each Endpoint

2.2.在每个端点中使用头的修改

As stated earlier, we can explicitly inject the ‘Access-Control-Allow-*‘ header at the endpoint level as well:

如前所述,我们也可以在端点层面明确注入”Access-Control-Allow-*“头。

@GET
@Path("/")
@Produces({MediaType.TEXT_PLAIN})
public Response index() {
    return Response
      .status(200)
      .header("Access-Control-Allow-Origin", "*")
      .header("Access-Control-Allow-Credentials", "true")
      .header("Access-Control-Allow-Headers",
        "origin, content-type, accept, authorization")
      .header("Access-Control-Allow-Methods", 
        "GET, POST, PUT, DELETE, OPTIONS, HEAD")
      .entity("")
      .build();
}

A point to note here is if we’re trying to enable CORS in a large application, we shouldn’t try this method because in this case, we have to manually inject the header into every URL endpoints which will introduce additional overhead.

这里需要注意的是,如果我们试图在一个大型的应用程序中启用CORS,我们不应该尝试这种方法,因为在这种情况下,我们必须手动将头注入每个URL端点,这将引入额外的开销。

However, this technique can be used in applications, where we need to enable CORS in only some of the URL endpoints.

然而,这种技术可以用在应用程序中,我们只需要在一些URL端点中启用CORS

3. Testing

3.测试

Once the application is up, we can test the headers using the curl commands. A sample headers output should be something like below:

一旦应用程序启动,我们就可以使用curl命令测试头文件。一个样本的头文件输出应该是如下的。

HTTP/1.1 200 OK
Date : Tue, 13 May 2014 12:30:00 GMT
Connection : keep-alive
Access-Control-Allow-Origin : *
Access-Control-Allow-Credentials : true
Access-Control-Allow-Headers : origin, content-type, accept, authorization
Access-Control-Allow-Methods : GET, POST, PUT, DELETE, OPTIONS, HEAD
Transfer-Encoding : chunked

What’s more, we can create a simple AJAX function and check the cross domain functionality:

更重要的是,我们可以创建一个简单的AJAX函数并检查跨域功能。

function call(url, type, data) {
    var request = $.ajax({
      url: url,
      method: "GET",
      data: (data) ? JSON.stringify(data) : "",
      dataType: type
    });
 
    request.done(function(resp) {
      console.log(resp);
    });
 
    request.fail(function(jqXHR, textStatus) {
      console.log("Request failed: " + textStatus);
    });
};

Of course in order to actually perform the check, we’ll have to run this on a different origin than the API we’re consuming.

当然,为了实际执行检查,我们必须在与我们正在消费的API不同的起源上运行这个。

You can do that locally quite easily by running a client app on a separate port – since the port does determine the origin.

你可以通过在一个单独的端口上运行一个客户端应用程序,在本地很容易做到这一点 – 因为端口确实决定了来源。

4. Conclusion

4.结论

In this article, we showed about implementing CORS mechanism in JAX-RS based applications.

在这篇文章中,我们展示了在基于JAX-RS的应用程序中实现CORS机制。

Like always, the full source code is available over on GitHub.

像往常一样,完整的源代码可以在GitHub上找到