【问题标题】:Cross domain put call does not work with Access-Control-Allow-Origin跨域 put 调用不适用于 Access-Control-Allow-Origin
【发布时间】:2015-12-21 13:24:01
【问题描述】:

我面临与跨域 PUT 调用相关的问题,我已允许服务器端的 Access-Control-Allow-Origin 仍然无法正常工作。

    @PUT
    @Path("/getresponse/{caller}")
    @Produces({MediaType.APPLICATION_JSON})
    public Response getResponseData(@PathParam("caller") String caller ,@QueryParam("ticket")String ticket ,@FormParam("formParam") String data){


        ResponseBuilder resp;
        System.out.println("name of caller is -> "+ caller);
        System.out.println("query param ticket -> "+ ticket);
        System.out.println("form param data->" + data);
        Employee emp = new Employee();
        emp.setAge(23);
        emp.setName("data");
        Gson gson = new Gson();
        String responseJson =  gson.toJson(emp);
        resp=Response.ok(responseJson);//header("Access-Control-Allow-Origin", "*")
        resp.header("Access-Control-Allow-Origin", "*")
        .header("Access-Control-Allow-Methods", "GET, POST, PUT, OPTIONS");

         return resp.build();
    }

每当我从 jquery ajax 方法调用它时,它都会说 对预检请求的响应未通过访问控制检查:请求的资源上不存在“Access-Control-Allow-Origin”标头

我有上述服务的相同副本,但是当我调用该服务时使用 POST 签名,它调用服务没有任何问题 邮政服务代码是

    @POST
    @Path("/getresponses/{caller}")
    @Produces({MediaType.APPLICATION_JSON})
    public Response getResponseData1(@PathParam("caller") String caller ,@QueryParam("ticket")String ticket ,@FormParam("formParam") String data){


        ResponseBuilder resp;
        System.out.println("name of caller is -> "+ caller);
        System.out.println("query param ticket -> "+ ticket);
        System.out.println("form param data->" + data);
        Employee emp = new Employee();
        emp.setAge(23);
        emp.setName("data");
        Gson gson = new Gson();
        String responseJson =  gson.toJson(emp);
        resp=Response.ok(responseJson);//header("Access-Control-Allow-Origin", "*")
        resp.header("Access-Control-Allow-Origin", "*")
        .header("Access-Control-Allow-Methods", "GET, POST");
        return resp.build();
    }

我的客户端代码是

$(document).ready(function(){
    // for post service
    $('#sendcall').on('click',function(e){
        var dataTosend ="formParam=data to send";
        $.ajax({
              url: 'http://someip:8099/Jqgrid/rest/getdata/getresponses/data?ticket=tick',
              contentType : 'application/x-www-form-urlencoded',
              data :dataTosend,   
              type: 'POST',
              success: function(data){
                alert(data);
              }
            });
    });

    //for PUT service
    $('#sendcall2').on('click',function(e){
        var datatosend ="formParam=data to send";
        $.ajax({
              url: 'http://someip:8099/Jqgrid/rest/getdata/getresponse/aliahsan?ticket=tick',
              contentType : 'application/x-www-form-urlencoded',
              data :datatosend,   
              type: 'PUT',
              crossDomain:true,
              beforeSend: function (xhr) {

                    console.log('header added');
                },
              success: function(data){
                alert(data);
              }
            });
    });
});

请在这方面帮助我,为什么 PUT 不适用于此。 任何帮助将不胜感激

【问题讨论】:

  • 不要在方法中添加 CORS 标头。 Use a filter
  • 为什么在 @peeskillet 方法中使用过滤器但不使用 CORS 的原因
  • CORS 的工作原理是首先有一个预检请求,这是一个 OPTIONS 请求(在实际请求之前),以尝试获取 CORS 标头。所以方法中的标题没有任何意义。
  • @peeskillet 你能告诉我为什么在 POST 的情况下没有预检请求,但在 PUT 的情况下有预检请求??
  • 一般使用application/x-www-form-urlencoded,不需要预检。更常见的是 JSON 需要它。因此,由于内容类型,POST 不需要处理预检。在 PUT 中,您使用crossDomain: true 强制执行跨域请求。见jQuery.ajax。另请阅读有关 CORS 的更多信息,请参阅 here

标签: jersey cors put


【解决方案1】:

不要在资源方法中添加所有 CORS 标头,而是使用 Jersey 过滤器,如 in this post 所述。原因是 CORS 预检请求,在 HTTP access control (CORS) 中定义为:

“预检”请求首先通过OPTIONS方法向对方域上的资源发送一个HTTP请求,以确定实际请求是否可以安全发送。

所以该请求是一个 OPTIONS 请求,它期望返回“Accept-Xxx”CORS 标头以确定服务器允许的内容。因此,将标头放在资源方法中没有任何影响,因为请求是使用 OPTIONS HTTP 方法发出的,而您没有资源方法。这通常会导致向客户端发送 405 Method Not Allowed 错误。

当您在过滤器中添加标头时,每个请求都会通过此过滤器,甚至是 OPTIONS 请求,因此预检会获取相应的标头。

至于PUT,在上面的链接文档中也有描述(继续上面的引用)

跨站点请求会像这样进行预检,因为它们可能会对用户数据产生影响。特别是,在以下情况下会预检请求:

  • 它使用 GET、HEAD 或 POST 以外的方法。此外,如果 POST 用于发送 Content-Type 不是 application/x-www-form-urlencoded、multipart/form-data 或 text/plain 的请求数据,例如如果 POST 请求使用 application/xml 或 text/xml 将 XML 有效负载发送到服务器,则请求被预检。
  • 它在请求中设置自定义标头(例如,请求使用诸如 X-PINGOTHER 之类的标头)

这就是为什么 POST 请求不会遇到同样的问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-11-23
    • 2014-06-15
    • 1970-01-01
    • 2013-08-30
    • 2019-02-28
    • 2018-09-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多