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 阻止(无访问控制-允许-来源标头)
为啥我的 formdata POST 没有被 Cors 政策阻止?