1. 概述

本文将介绍如何在基于 JAX-RS 的系统中启用 CORS(跨域资源共享)机制。我们将通过一个 JAX-RS 应用示例,展示两种实现 CORS 的方法。

2. 启用 CORS 的两种方式

在 JAX-RS 中启用 CORS 主要有两种方案:

  1. 全局过滤器:通过过滤器自动为所有响应注入 CORS 头
  2. 手动注入:在每个接口单独添加 CORS 响应头

✅ 推荐使用过滤器方案,能统一管理且避免遗漏。
❌ 手动方案仅适用于少量接口的特殊场景,大型项目维护成本高。

2.1 使用过滤器方案

JAX-RS 提供了 ContainerResponseFilter 接口,用于全局处理 HTTP 响应。我们通过实现该接口创建自定义过滤器:

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

⚠️ 关键点说明:

  • 必须使用 @Provider 注解,否则 JAX-RS 运行时无法发现该过滤器
  • Access-Control-Allow-Origin: * 表示允许所有域名访问,生产环境应替换为具体域名
  • 过滤器会自动处理所有接口的响应,无需重复配置

2.2 手动注入响应头方案

当无法使用全局过滤器时(比如遗留系统限制),可直接在接口方法中注入 CORS 头:

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

⚠️ 注意事项:

  • 每个需要跨域的接口都要重复添加这些头,容易遗漏
  • 修改 CORS 策略时需要更新所有相关接口
  • 仅适用于接口数量极少的简单场景

3. 测试验证

启动应用后,可通过以下方式验证 CORS 配置:

3.1 使用 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

3.2 跨域 AJAX 测试

创建测试脚本(需运行在与 API 不同域的环境下):

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

💡 本地测试技巧:
将前端应用运行在不同端口(如 localhost:3000),API 运行在 localhost:8080,即可模拟跨域场景(端口不同即视为不同源)。

4. 总结

本文展示了在 JAX-RS 应用中实现 CORS 的两种方案:

  • 过滤器方案:推荐用于生产环境,统一管理且维护成本低
  • 手动注入方案:仅适用于特殊场景,需谨慎使用

完整示例代码可在 GitHub 获取。实际应用中,建议根据项目规模和安全需求选择合适方案。


原始标题:CORS in JAX-RS