JSP не показывает правильное содержимое UTF-8 для формы HTML POST - PullRequest
0 голосов
/ 08 января 2019

Я использую Java 11 с Tomcat 9 с последней версией JSP / JSTL. Я тестирую в Chrome 71 и Firefox 64.0 в Windows 10. У меня есть следующий тестовый документ:

<%@ page contentType="text/html; charset=UTF-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html lang="en-US">
<head>
  <meta charset="UTF-8"/>
  <title>Hello</title>
</head>
<body>
  <c:if test="${not empty param.fullName}">
    <p>Hello, ${param.fullName}.</p>
  </c:if>

  <form>
    <div>
      <label>Full name: <input name="fullName" /></label>
    </div>
    <button>Say Hello</button>
  </form>
</body>
</html>

Это, пожалуй, самая простая из возможных форм. Как вам известно, форма method по умолчанию get, форма action по умолчанию "" (отправка на ту же страницу), а форма enctype по умолчанию application/x-www-form-urlencoded.

Если я введу в поле имя «Flávio José» (известный бразильский исполнитель и музыкант) и отправлю заявку, форма будет отправлена ​​через HTTP GET на ту же страницу с помощью hello.jsp?fullName=Fl%C3%A1vio+Jos%C3%A9. Это правильно, и на странице написано:

Hello, Flávio José.

Если я изменю форму method на post и введу то же имя «Flávio José», вместо этого содержимое формы будет отправлено через POST с содержимым HTTP-запроса:

fullName=Fl%C3%A1vio+Jos%C3%A9

Это также кажется правильным. Но на этот раз на странице написано:

Hello, Flávio José.

Вместо того, чтобы рассматривать %C3%A как последовательность октетов UTF-8, JSP, похоже, думает, что это серия октетов ISO-8859-1 (или кодовая страница 1252 октета), и поэтому декодирует их неверно последовательность символов.

Но где он получает ISO-8859-1? Чего не хватает в моей странице JSP, чтобы указать правильную кодировку?

Отмечу также, что спецификация WHATWG говорит, что application/x-www-form-urlencoded октеты должны быть проанализированы как UTF-8 по умолчанию. Не нарушена ли спецификация сервлета Java? Как мне обойти это?

1 Ответ

0 голосов
/ 08 января 2019

Это вызвано Tomcat, но основной проблемой является спецификация Java Servlet 4, которая неверна и устарела.

Изначально HTML 4.0.1 говорил, что application/x-www-form-urlencoded кодированные октеты должны быть декодированы как US-ASCII . Спецификация сервлета изменила это, сказав, что, если кодировка запроса не указана, октеты должны быть декодированы как ISO-8859-1. Tomcat просто следует спецификации сервлета.

В спецификации сервлета Java есть две проблемы. Во-первых, современная интерпретация application/x-www-form-urlencoded заключается в том, что закодированные октеты должны быть декодированы с использованием UTF-8 . Вторая проблема заключается в том, что привязка декодирования октетов к кодировке ресурсов смешивает два уровня декодирования.

Еще раз посмотрите на это POST содержание:

fullName=Fl%C3%A1vio+Jos%C3%A9

Вы заметите, что это ASCII !! Не имеет значения, считаете ли вы кодировку HTTP-запроса POST равной ISO-8859-1, UTF-8 или US-ASCII - вы все равно получите те же символы Unicode до декодирования октеты! Какая кодировка используется для декодирования октетов кодирования, является совершенно отдельной.

В качестве еще одного примера, скажем, я загружаю текстовый файл instructions.txt, который четко помечен как ISO-8859-1 и содержит URI https://example.com/example.jsp?fullName=Fl%C3%A1vio+Jos%C3%A9. То, что текстовый файл имеет кодировку ISO-8859-1, означает ли это, что мне нужно декодировать %C3%A с использованием ISO-8859-1? Конечно, нет! Кодировка, используемая для декодирования символов URI , представляет собой отдельный уровень декодирования поверх типа содержимого charset ! Точно так же октеты значений, закодированных в application/x-www-form-urlencoded, должны быть декодированы с использованием UTF-8, независимо от основной кодировки ресурса.

Существует несколько обходных путей, некоторые из которых можно найти, просмотрев часто задаваемые вопросы по кодировке символов Tomcat, чтобы «везде использовать UTF-8» .

Установите кодировку символа запроса в вашем файле web.xml.

Добавьте в файл WEB-INF/web.xml следующее:

<request-character-encoding>UTF-8</request-character-encoding>

Этот параметр не зависит от реализации контейнера сервлета и определен в спецификации сервлета. (Вы также можете поместить его в файл conf/web.xml Tomcat, если хотите использовать глобальные настройки и не хотите изменять конфигурацию Tomcat.)

Установите SetCharacterEncodingFilter в файле web.xml.

Tomcat имеет собственный эквивалент: используйте org.apache.catalina.filters.SetCharacterEncodingFilter в файле WEB-INF/web.xml, как указано выше в разделе часто задаваемых вопросов Tomcat, и как показано в https://stackoverflow.com/a/37833977/421049,, приведенном ниже:

<filter>
  <filter-name>setCharacterEncodingFilter</filter-name>
  <filter-class>org.apache.catalina.filters.SetCharacterEncodingFilter</filter-class>
  <init-param>
    <param-name>encoding</param-name>
    <param-value>UTF-8</param-value>
  </init-param>
</filter>

<filter-mapping>
  <filter-name>setCharacterEncodingFilter</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>

Это заставит ваше веб-приложение работать только на Tomcat, поэтому лучше поместить его в установочный файл Tomcat conf/web.xml, как упоминалось выше. Фактически установки Tomcat conf/web.xml имеют эти два раздела, но закомментированы; просто раскомментируйте их, и все должно работать.

Принудительная кодировка символов запроса в UTF-8 в JSP или сервлете.

Вы можете принудительно ввести кодировку символов запроса сервлета в UTF-8, где-то в начале JSP:

<% request.setCharacterEncoding("UTF-8"); %>

Но это уродливо, громоздко, подвержено ошибкам и идет вразрез с современными лучшими практиками - больше не следует использовать JSP-скриптлеты.

Надеемся, что мы сможем получить более новую спецификацию Java-сервлета, чтобы удалить любые отношения между набором ресурсов и декодированием application/x-www-form-urlencoded октетов и просто заявить, что application/x-www-form-urlencoded октеты должны быть декодированы как UTF-8, как это принято в современной практике. уточнено по последним спецификациям W3C и WHATWG.

Обновление: Я обновил часто задаваемые вопросы Tomcat по Проблемы кодировки символов с этой информацией.

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