Spring 格式和 UTF-8 错误编码
Spring form and UTF-8 bad encoding
在我们的 Web 应用程序中,我们遇到了错误的编码问题。为了重现此问题,用户在浏览器中选择非 unicode 编码(例如 chrome -> More tools->encoding->Koi8)并尝试设置 Cyrillic 文本。
当它进入控制器时,字符被破坏了(刚刚在调试时检查过),甚至它存储不正确和呈现不正确。
我们遵循了所有建议:http://balusc.blogspot.com/2009/05/unicode-how-to-get-characters-right.html 似乎这是提交 application/x-www-form-urlencoded
编码内容类型的问题。因为在提交此类表单时不可能设置字符集。
例如,如果使用 json 提交相同的数据并设置必要的内容类型,则一切都会正确存储。
我们还尝试了本文的示例:
http://www.codejava.net/frameworks/spring/spring-mvc-form-handling-tutorial-and-example 并使用以下方法额外添加 UTF8 文件管理器:
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException,
ServletException {
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
chain.doFilter(request, response);
}
但同样的问题是可以重现的。
有人可以建议如何解决上述问题吗?
是否可以在 Spring MVC 中正确处理提到的用例,因为我们尝试了简单的示例,但它似乎不起作用。这个更改浏览器编码的用例是否有效?
尝试:在web.xml
<filter>
<filter-name>encoding-filter</filter-name>
<filter-class>
org.springframework.web.filter.CharacterEncodingFilter
</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encoding-filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
参考:http://wiki.apache.org/tomcat/FAQ/CharacterEncoding
另外,如果你使用jstl,请尝试设置默认编码
在您的请求管道中的某个地方,您覆盖了编码(即在没有正确编码的情况下调用了 String.getBytes()
或 new String(bytes)
。
有很多地方可能会发生这种情况,这也是 Spring Boot 和各种其他框架强制使用 UTF-8 输入和输出的原因之一,特别是因为 UTF-8 是推荐的编码。
您的用户不应更改编码。事实上,当页面加载 servlet 响应和 HTML 本身时,应该指定 UTF-8,这是有充分理由的。服务器说 "I speak UTF-8"。如果您想要不同的编码,您必须在 HTML(即 jsp)和 servlet request/responses 中指定不同的编码,这样浏览器就会自动 select编码。即使这样,application/x-www-form-urlencoded
的里程数也会有所不同,特别是如果您使用 Javascript(可能是因为其他字符的编码规范有些含糊不清)。为了给您更多示例,说明为什么 HTML 必须具有与您发送的完全相同的编码,因为名称值对将具有不同的编码。那是您的表单具有 UTF-8 请求参数名称(因为那是 HTML 中的内容)但是当您覆盖它时,您为参数值提供了不同的编码(即 ?UTF-8Name=KoiValue&UTF-8Name=KoiValue
)。希望你能明白为什么这很糟糕,我不确定 chrome 是否足够聪明(或者它是否应该这样做)将请求参数名称更改回 Koi8。
因此,如果您绝对必须支持其他字符编码,您可能应该使用 multipart/form
(您在表单元素的 enctype
属性中指定)并且不要使用设置 UTF- 的编码过滤器8 因为这些可能会导致腐败。
此行为可以通过在表单中使用 accept-charset="UTF-8"
属性来实现。
可以在spring表单标签中添加。 struts 的旧版本也有一个错误(1.1 受到影响)
https://issues.apache.org/jira/browse/STR-1636
这使得无法将此属性直接添加到表单中。作为解决方法,可以使用 jQuery
jQuery( document ).ready(function() {
jQuery("#formSelector").attr("accept-charset", "UTF-8");
});
简而言之,此属性将强制浏览器使用指定的编码从该表单发送数据。如果用户将一些控制字符设置到输入中,它们也将被发送到后端,因此需要进行验证以防止这种情况。也会处理浏览器编码和键盘语言不能很好地协同工作的情况(例如 KOI8-U 和中文键盘语言)。
在我们的 Web 应用程序中,我们遇到了错误的编码问题。为了重现此问题,用户在浏览器中选择非 unicode 编码(例如 chrome -> More tools->encoding->Koi8)并尝试设置 Cyrillic 文本。
当它进入控制器时,字符被破坏了(刚刚在调试时检查过),甚至它存储不正确和呈现不正确。
我们遵循了所有建议:http://balusc.blogspot.com/2009/05/unicode-how-to-get-characters-right.html 似乎这是提交 application/x-www-form-urlencoded
编码内容类型的问题。因为在提交此类表单时不可能设置字符集。
例如,如果使用 json 提交相同的数据并设置必要的内容类型,则一切都会正确存储。
我们还尝试了本文的示例:
http://www.codejava.net/frameworks/spring/spring-mvc-form-handling-tutorial-and-example 并使用以下方法额外添加 UTF8 文件管理器:
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException,
ServletException {
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
chain.doFilter(request, response);
}
但同样的问题是可以重现的。
有人可以建议如何解决上述问题吗?
是否可以在 Spring MVC 中正确处理提到的用例,因为我们尝试了简单的示例,但它似乎不起作用。这个更改浏览器编码的用例是否有效?
尝试:在web.xml
<filter>
<filter-name>encoding-filter</filter-name>
<filter-class>
org.springframework.web.filter.CharacterEncodingFilter
</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encoding-filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
参考:http://wiki.apache.org/tomcat/FAQ/CharacterEncoding
另外,如果你使用jstl,请尝试设置默认编码
在您的请求管道中的某个地方,您覆盖了编码(即在没有正确编码的情况下调用了 String.getBytes()
或 new String(bytes)
。
有很多地方可能会发生这种情况,这也是 Spring Boot 和各种其他框架强制使用 UTF-8 输入和输出的原因之一,特别是因为 UTF-8 是推荐的编码。
您的用户不应更改编码。事实上,当页面加载 servlet 响应和 HTML 本身时,应该指定 UTF-8,这是有充分理由的。服务器说 "I speak UTF-8"。如果您想要不同的编码,您必须在 HTML(即 jsp)和 servlet request/responses 中指定不同的编码,这样浏览器就会自动 select编码。即使这样,application/x-www-form-urlencoded
的里程数也会有所不同,特别是如果您使用 Javascript(可能是因为其他字符的编码规范有些含糊不清)。为了给您更多示例,说明为什么 HTML 必须具有与您发送的完全相同的编码,因为名称值对将具有不同的编码。那是您的表单具有 UTF-8 请求参数名称(因为那是 HTML 中的内容)但是当您覆盖它时,您为参数值提供了不同的编码(即 ?UTF-8Name=KoiValue&UTF-8Name=KoiValue
)。希望你能明白为什么这很糟糕,我不确定 chrome 是否足够聪明(或者它是否应该这样做)将请求参数名称更改回 Koi8。
因此,如果您绝对必须支持其他字符编码,您可能应该使用 multipart/form
(您在表单元素的 enctype
属性中指定)并且不要使用设置 UTF- 的编码过滤器8 因为这些可能会导致腐败。
此行为可以通过在表单中使用 accept-charset="UTF-8"
属性来实现。
可以在spring表单标签中添加。 struts 的旧版本也有一个错误(1.1 受到影响)
https://issues.apache.org/jira/browse/STR-1636
这使得无法将此属性直接添加到表单中。作为解决方法,可以使用 jQuery
jQuery( document ).ready(function() {
jQuery("#formSelector").attr("accept-charset", "UTF-8");
});
简而言之,此属性将强制浏览器使用指定的编码从该表单发送数据。如果用户将一些控制字符设置到输入中,它们也将被发送到后端,因此需要进行验证以防止这种情况。也会处理浏览器编码和键盘语言不能很好地协同工作的情况(例如 KOI8-U 和中文键盘语言)。