对选项的 POST 更改 + 对预检请求的响应未通过访问控制检查:没有"访问控制-允许源"标头



XMLHttpRequest无法加载http://xxx.xxx.飞行前的反应请求未通过访问控制检查:否请求的上存在"Access Control Allow Origin"标头资源因此,不允许访问源"null"。回应具有HTTP状态代码500。

我试图用ajax发送一个xml soap,但出现了错误。我尝试了很多选项,但似乎都不起作用,下面是代码:

var soapMessage =
'<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:wsdl="http://xxx.xxx/">'+
'<soapenv:Header/>'+
'<soapenv:Body>'+
'<wsdl:test1>'+
'<PUI>12345</PUI>'+
'</wsdl:test1>'+
' </soapenv:Body>'+
'</soapenv:Envelope>';
$.ajax({
url: 'http://xxx.xxx', 
type: 'POST',
dataType: 'xml', 
data: soapMessage, 
crossDomain: true,
processData: false,
contentType: 'text/xml; charset="utf-8"',
headers: {
SOAPAction: "http://xxx.xxx"
},
success: function (msg, data) {
alert(msg);
},
error: function (msg, data) {
alert("Error");
}
});

我在这里做错了什么?我发送了一个POST操作,但它读作OPTION。如何解决此问题?

我使用BoomerangRestandSoapClient来测试这项服务,它给了我正确的响应。当我如上所述使用自己的程序时,它会导致XMLHttpRequest无法加载http://xxxxx"错误。我使用的是apache tomcat 6.0,代码使用的是Java web应用程序

您正在跨来源地进行请求,因此向其发出请求的服务器必须发送Access-Control-Allow-Origin响应标头,以表明它允许跨来源地请求。

请参阅https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS详细信息。

出于安全原因,浏览器限制从脚本内启动的跨源HTTP请求。例如,XMLHttpRequest和Fetch遵循同源策略。因此,使用XMLHttpRequest或Fetch的web应用程序只能向自己的域发出HTTP请求。

发生OPTIONS请求的原因是,当您发送具有除application/x-www-form-urlencodedmultipart/form-datatext/plain之外的值的Content-Type标头的跨源请求时,浏览器首先会进行CORS预检查。

您的请求发送Content-Type: text/xml; charset="utf-8",因此会导致飞行前。

就解决方案而言,如果发送请求的服务器不是您控制和可以配置的服务器,则可以使用开放的反向代理,如https://cors-anywhere.herokuapp.com/.

它的工作方式是,您不直接将请求发送到http://xxx.xxx,而是将其发送到https://cors-anywhere.herokuapp.com/http://xxx.xxx它代理您的请求并使用Access-Control-Allow-Origin和其他预期的CORS头进行响应。

当然,您需要意识到,如果您的请求包含任何凭据,那么您将向cors-anywhere.herokuapp.com的维护人员公开这些凭据。

我为此所做的工作是编写一个过滤器,将原点作为可接受的原点附加到任何选项请求上,并将其添加到需要接受此类请求的任何servlet中。这是我的实现:

public class CorsFilter implements Filter {
private static List<String> validServers = Arrays.asList([you need to fill this in with whatever sites you want to allow access]);
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
if (servletRequest instanceof HttpServletRequest) {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
String origin = request.getHeader("Origin");
if (StringUtils.isNotBlank(origin)) { //this is a cors request
boolean hasPrefix = origin.contains("/");
boolean hasPort = origin.contains(":");
String serverAlias = origin.substring(hasPrefix ? origin.lastIndexOf("/") + 1 : 0, hasPort ? origin.lastIndexOf(":") : origin.length());
if (validServers.contains(serverAlias)) {
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Methods", "OPTIONS, POST, GET, PUT, DELETE");
response.setHeader("Access-Control-Allow-Origin", origin);
response.setHeader("Access-Control-Allow-Headers", "Content-Type");
//credentials are not sent on options requests, kick out here so that the access control headers and nothing else can be returned
if ("OPTIONS".equals(request.getMethod())) {
response.setStatus(200);
return;
}
} else {
response.sendError(HttpStatus.SC_FORBIDDEN);
response.flushBuffer();
return;
}
}
}
filterChain.doFilter(servletRequest, servletResponse);
}

@Override
public void destroy() {
}
}

相关内容

最新更新