【问题标题】:Safe HTML form accept charset?安全的 HTML 表单接受字符集?
【发布时间】:2013-02-23 02:00:19
【问题描述】:

我在使用 get 方法提交表单时遇到了参数编码问题(我不能使用 post 方法)。由于我的页面是 UTF8,因此 URL 中的一些重音字符没有转义。 Spring 控制器取而代之的是检索到错误字符。

我通过在表单上设置accept-charset="ISO-8859-1" 解决了这个问题,但现在,我想知道对于所有服务器/浏览器组合,哪个字符集是安全。我的表单和“获取”网址有什么推荐的吗?

【问题讨论】:

  • 您应该确定 HTTP 请求参数的字符编码,而不仅仅是接受默认的 ISO-8859-1 设置。如果您的页面使用 UTF-8,则通过 tomcat server.xml 或本文 stackoverflow.com/a/5446467/249327 中所述的过滤器设置 HTTP 请求字符编码。

标签: html forms spring-mvc character-encoding


【解决方案1】:

这对于 servlet 来说是令人沮丧的(委婉地说)。标准 URL 编码必须使用 UTF-8,但 servlet 不仅默认为 ISO-8859-1,而且不提供任何通过代码更改它的方法。

当然,您可以在阅读任何内容之前req.setRequestEncoding("UTF-8"),但出于某些不虔诚的原因,这只会影响请求正文,而不影响查询字符串参数。 servlet 请求接口中没有指定查询字符串参数使用的编码。

在您的表单中使用ISO-8859-1 是一种黑客行为。使用这种古老的编码会导致比确定解决的问题更多的问题。特别是因为浏览器不支持 ISO-8859-1 并且始终将其视为 Windows-1252。而 servlet 将 ISO-8859-1 视为 ISO-8859-1,所以如果你这样做,你会变得难以置信。

例如,要在 Tomcat 中更改这一点,您可以在 <connector> 元素中使用 URIEncoding 属性:

<connector ... URIEncoding="UTF-8" ... />

如果您不使用具有这些设置的容器,无法更改其设置或其他问题,您仍然可以使其工作,因为 ISO-8859-1 解码保留了原始二进制文件的完整信息。

String correct = new String(request.getParameter("test").getBytes("ISO-8859-1"), "UTF-8")

假设test=ä,如果一切设置正确,浏览器会将其编码为test=%C3%A4。您的 servlet 将错误地将其解码为 ISO-8859-1 并为您提供结果字符串 "ä"。如果你应用更正,你可以得到ä 回复:

System.out.println(new String("ä".getBytes("ISO-8859-1"), "UTF-8").equals("ä"));
//true

【讨论】:

  • +1 因为这个详细的答案值得更多的支持。而且因为我的投票是对编写 servlet API 的编码人员的象征性反对...
【解决方案2】:

nickdos 是对的。 另一种方法是使用元数据标签:

<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8">

另外请记住,在服务器上处理响应时,代码也应该使用正确(相同)的编码。

例子:

使用stringParamer.getBytes("utf-8") instead of stringParamer.getBytes()

使用 Spring 时,请确保在 DispatcherServlet 的配置文件 (XYZ_-servlet.xml) 中为消息转换器配置正确的编码,例如:

<bean id="stringHttpMessageConverter" class="org.springframework.http.converter.StringHttpMessageConverter">
    <property name="supportedMediaTypes" value = "text/plain;charset=UTF-8"/>
</bean>

【讨论】:

    【解决方案3】:

    问题是 URL 总是被编码为 127-ASCII。因为您的表单通过 GET 发送回标准 ASCII 集之外的其他字符值,所以您遇到了几个问题:

    1. 网址限制为 2048 个字符,因此您的表单值可能会被截断
    2. 如果用户输入的字符超出了您在 Form 属性中设置的 ISO 接受类型,它们将无法正确编码到 URL 中。这是因为浏览器在第一次使用页面的编码后对 URL 进行编码时会将所有内容转换为 127-ASCII。任何不在该 ISO 集中的特殊字符都将被错误编码。
    3. 浏览器总是首先使用页面编码或元标记来翻译 URL 中的字符。但是,如果有一个服务器 HTTP 标头,该编码将覆盖您的元标记编码。 HTML5 页面的默认编码是 UTF-8。但是您使用的是覆盖它的 ISO 标准。即便如此,您的浏览器完成的所有编码都会用“%”替换非 ASCII 字符,后跟来自页面编码的十六进制数字,或者在您的情况下是表单的设置编码。然后将其发送到服务器,因此请查看您的 URL 以查看已发送的内容。
    4. 当您的 URL 到达服务器时,它以 127-ASCII 的形式出现,因此您需要首先将字符串作为 ASCII 获取,然后解码回页面编码,或者在您的情况下,表单接受用于获取真实的价值观。

    我建议您删除表单编码,使用页面 UTF-8 设置以获得更广泛的字符支持,并放入下面这两个元标记以确保您发送回 UTF-8 编码数据,其中包括所有需要的字符和如上所述,在服务器上很容易被其他海报所解码。

    <meta charset="utf-8" />
    <meta content="text/html; charset=utf-8" http-equiv="content-type" />
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-28
      • 1970-01-01
      • 1970-01-01
      • 2011-11-02
      • 2015-08-19
      • 2014-01-28
      相关资源
      最近更新 更多