在JSP中破坏UTF-8 URI编码

时间:2012-07-16 13:10:22

标签: java jsp encoding utf-8 tomcat6

错误的URI编码出现了一个奇怪的问题,非常感谢任何帮助!

该项目使用JSP,Servlets,Jquery,Tomcat 6。

JSP中的Charset设置为UTF-8,所有Tomcat连接器都使用URIEncoding = UTF-8,我还使用了here所述的字符编码过滤器。 此外,我在元标记中设置了contentType,我的浏览器正确检测到它。

在使用Jquery的Ajax调用中,我在要用作URL参数的术语上使用encodeURIComponent(),然后使用$ .param()序列化整个参数集。在被调用的servlet中,这些参数使用Java.net.URLDecoder.decode(术语“UTF-8”)正确解码。

在某些地方,我从JSP中的参数映射生成href元素的URL。每个参数值在JSP端使用Java.net.URLEncoder.encode(值,“UTF-8”)进行编码,然后以与之前相同的方式对其进行解码,从而导致特殊字符损坏。相反,我必须在JSP中将其编码为“ISO-8859-2”,然后在servlet中将其正确解码为“UTF-8”。

澄清的一个例子: 术语“überfall”通过Javascript(%C3%BCberfall)进行URIEncoded,并发送到servlet进行解码和处理,这有效。将它传回JSP后,我将其编码为UTF-8并构建URL,例如:

<a href="/myWebapp/servletPath?term=%C3%BCberfall">Click here</a>

但是,单击此链接会将参数“%C3%83%C2%BCberfall”发送到解码为“überfall”的servlet。没有编码时会发生同样的情况。

当使用“ISO-8859-2”进行编码时,我得到:

<a href="/myWebapp/servletPath?term=%FCberfall">Click here</a>

单击此链接时,我可以在Wireshark中观察到%C3%BCberfall作为参数发送,再次解码为“überfall”!

谁能告诉我哪里错过了什么?

编辑: 在观察Firebug中的网络选项卡时,我意识到使用

$.param({term : encodeURIComponent(term)}); 

该术语是UTF-8编码两次,导致“%25C3%25BCberfall”,即百分比符号也是百分比编码的。类似地,如果我对参数图中的每个值调用encode(term,“UTF-8”)两次,它对我有用。

编码一次而不解码字符串会再次导致“überfall”。

2 个答案:

答案 0 :(得分:1)

Java在内部使用什么编码?您是否以

开始申请?
-Dfile.encoding=utf-8

请说明定义“JSP中的参数映射”的位置。它是来自某些持久性数据存储,还是代码中给出的字符串作为文字?

对正在发生的事情的一些想法,这可能会有所帮助:

ü是在UTF-8编码ü读取期望ISO-8859-1时,每个字节自行解码时出现的内容。 %C3%BCUTF-8 UTF-8的{​​{1}}字节的URI编码表示形式。我认为这就是发生的事情:

ü 错误地解码为→ %C3%BC ,其编码为→ {{1然后再次解码为 ü ,以便最终得到%C3%83%C2%BC

所以我想,您使用错误的编码来解码URI编码的字符串。这可能与Java / JVM使用的内部编码有关:

  

By default, the JRE 7 installer installs a European languages version if it recognizes that the host operating system only supports European languages.

答案 1 :(得分:1)

我想我现在肯定已经解决了这个问题。

根据Jontro的评论,我编写了所有URL参数值一次,并删除了手动servlet端解码。

在Firebug的“网络”标签中发送ü应该看起来像%C3%BC,它在servlet中提供了ü。 Java肯定是使用-Dfile.encoding参数设置为“UTF-8”内部编码。 我将问题跟踪到这样的request.getParameter()方法。 request.getQueryString没问题,但在提取实际参数时失败了:

  

request.getCharacterEncoding())=&gt; UTF-8
     request.getContentType()=&gt;空
     request.getQueryString()=&gt;从= 0&安培; = RESULTCOUNT 10安培; sortAsc =真安培;检索类别=快速和安培;术语=%C3%BC
     request.getParameter(“term”)=&gt;那张
     Charset.defaultCharset()=&gt; UTF-8
     OutputStreamWriter.getEncoding()=&gt; UTF8
     new String(request.getParameter(“term”)。getBytes(),UTF-8)=&gt;那张
     System.getProperty(“file.encoding”)=&gt; UTF-8

通过查看实现request.getParameter()的Tomcat和Coyote的来源,我发现了问题:来自连接器的URIEncoding始终为null,在这种情况下,它默认为org.apache.coyote.Constants.DEFAULT_CHARACTER_ENCODING,这是像Wolfram所说的“ISO-8859-1”。

长话短说:我的错误是在Tomcat的conf目录中编辑server.xml,当在服务器视图中创建新服务器时,该目录仅将ONCE加载到Eclipse中!之后,必须编辑Servers项目中的单独server.xml。执行此操作后,连接器设置将正确加载,一切正常。

感谢您的评论!希望这有助于某人...