AJAX CORS 请求来源被阻止 - Java Web 服务

Posted

技术标签:

【中文标题】AJAX CORS 请求来源被阻止 - Java Web 服务【英文标题】:AJAX CORS Request Origin Blocked - Java Web Service 【发布时间】:2018-06-28 12:46:43 【问题描述】:

每次我们尝试通过 AJAX JQuery 访问我的 REST Web 服务时,都会被 Cross-Origin 阻止:

跨域请求被阻止:同源策略不允许读取 http://***** 上的远程资源 (原因:CORS 标头“Access-Control-Allow-Origin”缺失)。

我们在 Glassfish 3.1.2 上使用 Java REST Web 服务,客户端使用 Firefox Quantum 57。

请看下面的代码:

$.ajax(
    type: 'POST',
    url: webservice + "/webresources/ivi/syncPassphrase",
    crossOrigin: true,
    data :JSON.stringify(
      'passPhrase' : passphrase
    ),
    dataType: 'json',
    async: false,
    contentType: 'application/json; charset=utf-8',
    crossDomain: true,
    success: function(data) 
      syncData = data["output"];  
    , error: function()  

    
);

我们已经阅读了关于 SO 的几个答案,并尝试过如下方式:

$.ajax(
    type: 'POST',
    url: webservice + "/webresources/ivi/syncPassphrase",
    crossOrigin: true,
    data :JSON.stringify(
      'passPhrase' : passphrase
    ),
    xhrFields: 
        withCredentials: true
    ,
    dataType: 'json',
    async: true,
    contentType: 'application/json; charset=utf-8',
    crossDomain: true,
    timeout: 20000,
    beforeSend: function(xhr) 
        xhr.setRequestHeader("Access-Control-Allow-Origin",'http://111.111.111.111:8080');
    ,
    success: function(data) 
      syncData = data["output"];  
      console.log("xxx1 " + syncData);
    , error: function(xhr, status, error) 
      console.log("xxx2 " + xhr.responseText + " | " + status + " | " + error + " | ");
    
);

但上面的代码仍然会产生同样的错误。

在服务器端,我们设置了允许跨源每个请求并响应如下代码:

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

我没有主意了。有什么想法吗?

谢谢

【问题讨论】:

双重检查:(1) 过滤器实际被应用(通过调试它),(2) 标题没有被另一个过滤器覆盖(通过调试所有过滤器),(3 ) 当负载均衡器(如果使用)重写响应时,响应标头不会丢失 【参考方案1】:

有几点:

    您不需要在请求中发送 ACAO 标头 - 这段客户端代码什么都不做:

    beforeSend: function(xhr)
        xhr.setRequestHeader("Access-Control-Allow-Origin",'http://111.111.111.111:8080');
    ,
    

    Access-Control-Allow-Origin * (ACAO) 响应标头与 Access-Control-Allow-Credentials: true (ACAC) 标头不兼容。如果您需要 cookie 或身份验证,则必须指定 Access-Control-Allow-Origin: value-of-Origin-request-header

第二个可能会解决它。

更新

你的服务器代码应该是这样的:

@Override
public void filter(final ContainerRequestContext requestContext,
              final ContainerResponseContext cres) throws IOException 
  cres.getHeaders().add("Access-Control-Allow-Origin", "http://your-origin:port");
  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");

但将 http://your-origin:port 替换为发出请求的页面域(如果不是 80,则包括端口)。我不知道您的服务器代码,但如果您可以检索 Origin 请求标头的值,而不是对其进行硬编码,那就更好了。

这样更有意义吗?

【讨论】:

从第二个开始,我必须在哪里指定访问控制允许来源?在客户端还是服务器端?你能给我提供一些例子的更多细节吗? 您在服务器上添加 ACAO 标头。实际上,您现有的服务器代码看起来不错 - 只需将 ACAO 标头的值从星号更改为传入 Origin 请求标头的值。保持 ACA 标头不变。其中一些标头在对 GET 或 POST 的响应中不需要(它们仅在预检 OPTIONS 请求中需要),但如果您将它们留在那里,它们不会破坏任何东西。 您提到ACAO header from an asterisk to the value of the incoming Origin request header.,实际上传入的原始请求标头来自客户端并使用许多IP地址。这个怎么样? Origin 标头是什么并不重要(可能是 https://www.example.com 或者可能是 https://127.0.0.1:8080 或其他) - 只需将其镜像回 ACAO 响应标头中即可。如果没有 Origin 请求标头,那么您无论如何都不需要 CORS。 显然,我不明白。你能给我举个例子吗?

以上是关于AJAX CORS 请求来源被阻止 - Java Web 服务的主要内容,如果未能解决你的问题,请参考以下文章

当我在控制器功能中间中止或退出时,Ajax 请求被 Cors 阻止

春季网关请求被 CORS 阻止(无访问控制-允许-来源标头)

请求被 CORS 策略阻止

为啥我的 formdata POST 没有被 Cors 政策阻止?

js ajax跨域被阻止 CORS 头缺少 'Access-Control-Allow-Origin'(转)

获取错误来源“null”已被 CORS 策略阻止?