JSP no mostrar los contenidos UTF-8 correctos para POST de formulario HTML

Garret Wilson:

Estoy usando Java 11 con Tomcat 9 con la última JSP / JSTL. Estoy probando en Chrome 71 y Firefox 64.0 en Windows 10. Tengo el siguiente documento de prueba:

<%@ 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>

Esta es quizás la forma más simple posible. Como ya saben los formularios methodde forma predeterminada get, la forma actionpor defecto ""(enviar a la misma página), y de la forma enctypepor defecto application/x-www-form-urlencoded.

Si entro en el nombre de "José Flávio" (un famoso cantante de forró brasileño y músico) en el campo y presento, el formulario se envía a través de HTTP GETa la misma página utilizando hello.jsp?fullName=Fl%C3%A1vio+Jos%C3%A9. Esto es correcto, y la página dice:

Hello, Flávio José.

Si cambio la forma methodde poste introduzca el mismo nombre "Flávio José", el contenido del formulario se presentaron en su lugar por medio POST, con contenidos HTTP de solicitud:

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

Esto también parece correcta. Pero esta vez la página dice:

Hello, Flávio José.

En lugar de ver %C3%Acomo una secuencia de octects UTF-8, JSP parece pensar que se trata de una serie de ISO-8859-1 octetos (o página de códigos 1252 octetos), y por lo tanto se les decodificando a la secuencia de caracteres incorrecto.

Pero ¿dónde está recibiendo ISO-8859-1? ¿Cuál es mi página JSP para indicar que carece de la codificación correcta?

Voy a señalar también que la especificación WHATWG dice que application/x-www-form-urlencodedoctetos deben ser analizados como UTF-8 por omisión. Es la especificación servlet de Java simplemente rota? ¿Cómo trabajo alrededor de esto?

Garret Wilson:

Esto es causado por Tomcat, pero la raíz del problema es la especificación de Java Servlet 4, que es incorrecta y obsoleta.

Originalmente HTML 4.0.1 dijo que application/x-www-form-urlencodedoctetos codificados deben ser decodificados como US-ASCII . La especificación servlet cambiado esto para decir que, si no se especifica la solicitud de codificación, los octetos deben ser decodificados como ISO-8859-1. Tomcat simplemente está siguiendo la especificación servlet.

Hay dos problemas con la especificación de servlets Java. La primera es que la interpretación moderna de application/x-www-form-urlencodedes que los octetos codificados deben ser decodificados con UTF-8 . El segundo problema es que atar el octeto de decodificación para el conjunto de caracteres de recursos confunde dos niveles de decodificación.

Echar otro vistazo a este POSTcontenido:

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

Se dará cuenta de que es ASCII !! No importa si se considera la POSTpetición HTTP juego de caracteres a ser ISO-8859-1, UTF-8o US-ASCII-Ya lo todavía terminan con exactamente los mismos caracteres Unicode antes de decodificar los octetos! Qué codificación se utiliza para decodificar los octetos que codifican está completamente separada.

Como otro ejemplo, digamos que se descarga un archivo de texto instructions.txtque está claramente marcado como ISO-8859-1, y contiene el URI https://example.com/example.jsp?fullName=Fl%C3%A1vio+Jos%C3%A9. El hecho de que el archivo de texto tiene un juego de caracteres ISO-8859-1, ¿significa que es necesario decodificar %C3%Ausando la norma ISO-8859-1? ¡Por supuesto no! El conjunto de caracteres utilizado para decodificar caracteres URI es un nivel separado de decodificación en la parte superior del juego de caracteres de recursos tipo de contenido ! Del mismo modo los octects de valores codificados en application/x-www-form-urlencodeddeben ser decodificados usando UTF-8, independientemente de la charset subyacente del recurso.

Hay varias soluciones, algunos de ellos encontraron a encontrar buscando en el carácter Tomcat codificación de Preguntas al "uso de UTF-8 en todas partes" .

Establecer la codificación de caracteres solicitud en su web.xmlarchivo.

Añadir lo siguiente a su WEB-INF/web.xmlarchivo:

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

Este ajuste es agnóstico de la aplicación contenedor servlet, y se define adelante en la especificación servlet. (Debe ser capaz de poner alternativamente en Tomcat de conf/web.xmlarchivo, si quieres un entorno global y no le importa cambiar la configuración de Tomcat).

Ajuste el SetCharacterEncodingFilteren su web.xmlarchivo.

Tomcat tiene un equivalente de propiedad: utilizar el org.apache.catalina.filters.SetCharacterEncodingFilteren el WEB-INF/web.xmlarchivo, como el Tomcat FAQ anterior menciona, y como se ilustra por https://stackoverflow.com/a/37833977/421049 , un extracto a continuación:

<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>

Esto hará que su aplicación web única obra en Tomcat, por lo que es mejor poner esto en la instalación de Tomcat conf/web.xmlarchivo en lugar, como el post anterior menciona. De hecho de Tomcat conf/web.xmlinstalaciones tienen estas dos secciones, pero comentado; simplemente descomentarlas y deben funcionar las cosas.

Forzar el carácter solicitud de codificación UTF-8 en la JSP o servlet.

Puede forzar la codificación de caracteres de la petición de servlet a UTF-8, en algún lugar temprano en la JSP:

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

Pero eso es feo, difícil de manejar y propenso a errores, y va en contra de las prácticas modernas mejores scriptles-JSP no debe utilizarse más.

Con suerte podemos conseguir una especificación de servlets de Java más reciente para eliminar cualquier relación entre el juego de caracteres de recursos y la decodificación de application/x-www-form-urlencodedoctetos, y simplemente estado que application/x-www-form-urlencodedoctetos deben ser decodificados como UTF-8, como es la práctica moderna como aclara la última W3C y las especificaciones WHATWG.

Actualización: He actualizado el Tomcat FAQ en caracteres problemas de codificación con esta información.

Supongo que te gusta

Origin http://43.154.161.224:23101/article/api/json?id=181324&siteId=1
Recomendado
Clasificación