Почему CORS-запрос не выполняется даже после установки "esponse.addHeader (" Access-Control-Allow-Origin "," * ");" в сервлете? - PullRequest
1 голос
/ 20 мая 2019

У меня есть вопрос, связанный с сервлетом Tomcat, работающим на облачном сервере.

У меня есть веб-приложение, состоящее из (в настоящее время):

• 13 файлов HTML в папке

• отдельный файл CSS в подпапке с именем «css»

• отдельный файл Javascript (JS), расположенный в подпапке с именем «js», который содержит ряд библиотечных функций, включая функцию запроса CORS

• сервлет Java, упакованный в файл WAR

• файл web.xml

• база данных MySQL

Я протестировал это приложение на своем ноутбуке, используя NetBeans (с WildFly в качестве веб-сервера), 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-код

На стороне сервера, в начале кода 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);
}

Файл 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’).

Если код выполнен правильно, в одном из окон SELECT в моем веб-браузере будет показан список состояний. Но, конечно, я ничего не заполняю из-за ошибки CORS. Любая помощь будет принята с благодарностью!

1 Ответ

0 голосов
/ 23 мая 2019

Я сталкивался с этой проблемой раньше, когда, по сути, из кода javascript вам не разрешено создавать запрос с ContentType, для которого задано значение application / json для серверного сервлета.

Типы содержимого, приемлемые изjavascript / веб-сайт для бэкэнда для запроса:

  1. application / x-www-form-urlencoded
  2. multipart / form-data
  3. текст / обычный

Короче говоря, измените тип содержимого Javascript CORS на 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, либотекст / обычный).Они называются простыми заголовками, и вам не нужно указывать их явно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...