如何摆脱No 'Access-Control-Allow-Origin'头出现在基于Java的web服务

How to get rid of No 'Access-Control-Allow-Origin' header is present on the requested resource error in java based web-service server

本文关键字:Java 服务 web No 何摆脱 Access-Control-Allow-Origin      更新时间:2023-09-26

我试图建立一个web服务(基于Java的服务器和Javascript基础客户端)我只需要发送一个json数据的Post请求,我需要从服务器获得一个json数据的Post响应。由于客户端和服务器有不同的域,我认为需要支持cors。到目前为止,我已经实现了这些:(我的客户端实现几乎与html5流程教程相同)

Web service client (js):

    // I call client = new WSclient() in one of my js files   
    WSclient=function(){
      makeCorsRequest();
    }
    // Create the XHR object.
    function createCORSRequest(method, url) {
      var xhr = new XMLHttpRequest();
      if ("withCredentials" in xhr) {
        // XHR for Chrome/Firefox/Opera/Safari.
        xhr.open(method, url, true);
      } else if (typeof XDomainRequest != "undefined") {
        // XDomainRequest for IE.
        xhr = new XDomainRequest();
        xhr.open(method, url);
      } else {
        // CORS not supported.
        xhr = null;
      }
      return xhr;
    }
    // Helper method to parse the title tag from the response.
    function getTitle(text) {
      return text;
    }
    // Make the actual CORS request.
    function makeCorsRequest() {
      // All HTML5 Rocks properties support CORS.
      var url = 'http://localhost:8080/myapp/myfunction';
      var xhr = createCORSRequest('POST', url);
      xhr.setRequestHeader(
          'X-Custom-Header', 'value');
      xhr.send();
    }

Web服务服务器(java)

@Path("/myapp/")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public class myFunctionClass {

    @POST
    @Path("myfunction")
    public Response recommendations(User inf){
        // From the client I also need to send json 
        // like {"name":"john","surname":"smith","name":"marry","surname":"smith"}
        // and if possible I want to put this infformation inside inf object
        List<String> infos = inf.getInformation();
         // here I call one of the my methods to get recommendations
         // I remove it for simplicity and just put type of recommendations object 
         // list<Recommendation> recommendations= runFunction(infos);
        final StringWriter sw =new StringWriter();
        final ObjectMapper mapper = new ObjectMapper();
        mapper.writeValue(sw, recommendations);
        System.out.println(sw.toString());
        sw.close(); 

        return Response.ok(sw.toString(), MediaType.APPLICATION_JSON).header("Access-Control-Allow-Origin", "*")
                .header("Access-Control-Allow-Methods", "POST").allow("OPTIONS").build();

    }
}

然而,我认为我需要做更多的事情,因为当我运行这些,我得到

    XMLHttpRequest cannot load      http://localhost:8080/myapp/myfunction. 
No 'Access-Control-Allow-Origin' header is present on the requested resource. 
Origin 'http://localhost:3000' is therefore not allowed access.

那么我应该在服务器代码中添加什么来消除这个错误呢?此外,我如何在客户端请求中发送json数据?这是我第一次处理这样的问题,因此,如果我的问题有点荒谬,我很抱歉。

编辑

删除

 xhr.setRequestHeader(
              'X-Custom-Header', 'value');  

部分,工作正常。正如我之前所说的,这是我第一次使用web服务和javascript,所以实际上我不知道这行代码是做什么的。谁能告诉我如果它存在会发生什么?

EDIT2

我明白了,我需要把

xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8");

以便发送带有请求的json。但是当我加上这个,同样的错误又回来了。我应该向服务器添加什么来实现这一点?

发生的事情是,在初始请求之前有一个预飞行请求(这是一个OPTIONS请求)。因此,您需要一个@OPTIONS端点来处理该请求(即设置响应头)。在当前代码中,您试图在原始请求的端点响应中设置它,而OPTIONS请求甚至无法到达。

一种更常见的方法,而不是为每个目标创建@OPTIONS端点,只需使用Jersey过滤器,如本答案所示。对于所有的请求,报头都会被发送出去。

参见:

    HTTP访问控制(CORS)

编辑

例子@OPTIONS

@OPTIONS
@Path("myfunction")
public Response cors() {
    return Response.ok()
        .header("Access-Control-Allow-Origin", "*")
        .header("Access-Control-Allow-Methods",
            "GET, POST, PUT, DELETE, OPTIONS, HEAD")
        // whatever other CORS headers
        .build();
}