为什么即使设置了“ esponse.addHeader(“ Access-Control-Allow-Origin”,“ *”);, CORS请求仍然失败在servlet中?

时间:2019-05-20 18:22:03

标签: javascript java tomcat servlets cors

我有一个关于在云服务器上运行的Tomcat托管的servlet的问题。

我有一个Web应用程序,由(目前)组成:

•文件夹中有13个HTML文件

•位于名为“ css”的子文件夹中的单独的CSS文件

•位于名为“ js”的子文件夹中的单独的Javascript(JS)文件,其中包含许多库函数,包括CORS请求函数

•打包在WAR文件中的Java servlet

•一个web.xml文件

•MySQL数据库

我已经使用NetBeans(将WildFly作为Web服务器),MySQL和FireFox浏览器在笔记本电脑上测试了该应用程序,一切运行正常。

然后,我在云服务器上设置Tomcat,复制数据库,并安装WAR和web.xml文件,并使用Tomcat控制面板设置上下文路径。

我已经咨询了这里和其他位置的论坛,并检查了云托管提供商的论坛。我认为我正在做所有需要启用CORS请求的事情,但是我在某个地方犯了一些细微的错误,或者我忽略了某些东西,而我目前处于僵局。

JavaScript代码

我的Javascript CORS函数(在JS库文件中)如下所示:

function createCORSRequest(method, url) {
    var xhr = new XMLHttpRequest();
//  xhr.withCredentials = true;     // do I even need to do this – and -
    xhr.withCredentials = "true";   // which is correct – string or logical?
    if ("withCredentials" in xhr) {
        // Check if the XMLHttpRequest object has a "withCredentials" property.
        // "withCredentials" only exists on XMLHTTPRequest2 objects.
        xhr.open(method, url, true);
        xhr.setRequestHeader("Content-Type", "application/json");  // is this correct?
    } else if (typeof XDomainRequest != "undefined") {
        // Otherwise, check if XDomainRequest.
        // XDomainRequest only exists in IE, and is IE's way of making CORS requests.
        xhr = new XDomainRequest();
        xhr.open(method, url);
        xhr.setRequestHeader("Content-Type", "application/json");  // is this correct?
    } else {
        // Otherwise, CORS is not supported by the browser.
        xhr = null;
    }
    return xhr;
}

此外,在同一文件的其他地方,我定义了函数的各种调用所需的常量:

var PARAM_CMD = "&cmd=";   
…
var CMD_GET_MAP = 310;
…
var PARAM_TBL = "&tbl=";
…
var PARAMS_GET_HASHMAP = PARAM_CMD + CMD_GET_MAP + PARAM_TBL;
…
var HASHMAP_STATES = 1130;
…
var urlname = "http://TestSite.com/TestServer/TestServer?autoReconnect=true&useSSL=false";

以下是此代码的典型调用:

function populateUSStatesBox() {
  var fullURL = urlname + PARAMS_GET_HASHMAP + HASHMAP_STATES;
  var xmlhttp = createCORSRequest("GET", fullURL);
  // handle changes to the request state
  xmlhttp.onreadystatechange = function () {
    if ((xmlhttp.readyState === XMLHttpRequest.DONE) && (xmlhttp.status === HTTP_RESP_OK)) {
      var StatesMap = JSON.parse(xmlhttp.responseText);
      setupComboBox ("cboUSStates", StatesMap);
    }
  }
  // send the http GET request with the command parameters sent in the header
  xmlhttp.send();
}

Java代码

在服务器端,靠近servlet doGet代码开头,我根据在各种论坛上看到的帖子设置响应头值。我实际上只发送[大多数] GET请求和一些POST(但目前不发送任何PUT,UPDATE,DELETE或OPTION)。我知道“ Access-Control-Allow-Origin”的“ *”值对生产很危险,但我刚刚将其打开进行测试。

public void doGet(HttpServletRequest request, HttpServletResponse response)
        throws IOException, ServletException {
   .
   .
   .
// response.addHeader("Access-Control-Allow-Origin", 
request.getHeader("Origin"));   // is this correct?
response.addHeader("Access-Control-Allow-Origin", "*");
response.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, UPDATE, OPTIONS, DELETE");
response.addHeader("Access-Control-Max-Age", "3600");
response.addHeader("Access-Control-Allow-Headers", 
   "Content-Type, Authorization, Content-Length, X-Requested-With");
response.addHeader("Access-Control-Allow-Credentials", "true");
response.addHeader("Cache-Control", "private, max-age=0, must-revalidate");
response.addHeader("Pragma", "public");
.
.
.
}
.
.
.
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
   doGet(request, response);
}

包含servlet的Java文件称为TestServer.java;程序包名称为TestServer。

配置信息

Tomcat目录结构(Linux / Centos)是:

var
   lib 
      tomcat 
         webapps
            TestServer
               TestServer.war
               WEB-INF
                  web.xml 
               META-INF
                  context.xml

context.xml包含以下内容:

<?xml version="1.0" encoding="UTF-8"?> 
<Context path="/TestServer"/>

web.xml文件具有以下内容:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.1" xmlns="http://xmlns.jcp.org/xml/ns/javaee"  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">
<servlet>
    <servlet-name>TestServer</servlet-name>
    <servlet-class> TestServer. TestServer </servlet-class>
    <display-name>Test System</display-name>
    <init-param>
        <param-name>loginName</param-name>
        <param-value>#####</param-value>   Note: I’ve obscured the LoginName
    </init-param>
    <init-param>
        <param-name>connectionPWD</param-name>
        <param-value>#####</param-value>  Note: I’ve obscured the connectionPWD
    </init-param>
    <init-param>
        <param-name>dbURL</param-name>
        <!--param-value>localhost/</param-value-->
        <!--param-value>jdbc:mysql://localhost:3306/</param-value-->
        <param-value>jdbc:mysql://127.0.0.1:3306/</param-value>
    </init-param>
    <init-param>
        <param-name>dbName</param-name>
        <param-value>#####</param-value>  Note: I’ve obscured the dbName
    </init-param>
    <init-param>
        <param-name>debugging</param-name>
        <param-value>on</param-value>
    </init-param>
</servlet>
<servlet-mapping>
    <servlet-name>TestServer</servlet-name>
    <url-pattern>/ TestServer</url-pattern>
</servlet-mapping>
<session-config>
    <session-timeout>
        30
    </session-timeout>
</session-config>
</web-app>

结果

当我尝试在本地系统上加载这些网页之一时,我在Firefox控制台中报告了以下错误(Chrome和Opera中也是如此)

跨域请求被阻止:“同源起源”策略禁止读取http://testsite.com/TestServer/TestServer?autoReconnect=true&useSSL=false&cmd=310&tbl=1130处的远程资源。 (原因:CORS标头“ Access-Control-Allow-Origin”缺失)。

如果代码正确执行,则Web浏览器中的SELECT框之一将显示状态列表。但是,当然,由于CORS错误,我一无所获。任何帮助将不胜感激!

1 个答案:

答案 0 :(得分:-1)

之前我曾遇到过这个问题,从本质上讲,您不允许使用javascript代码创建将ContentType设置为application / json到后端servlet的请求。

从javascript /网站到后端的内容类型都可以接受:

  1. application / x-www-form-urlencoded
  2. multipart / form-data
  3. 文本/纯文本

因此,简而言之,将您的Javascript CORS Content-Type更改为3之一。

这里有更多有关https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Headers#Directives的信息

  

请注意,始终允许使用某些标头:Accept,Accept-Language,Content-Language,Content-Type(但仅限于MIME)   其解析值的类型(忽略参数)   application / x-www-form-urlencoded,multipart / form-data或   文字/纯文字)。这些被称为简单标题,您不需要   明确指定它们。