又一个URI请求参数编码有关问题

又一个URI请求参数编码问题

     今天又遇到一个URL请求参数的编码问题,排查了差不多半天左右,写出来和大家分享一下:

问题1描述:

     项目中用到JSON接口,这个JSON接口接受一个可能带有中文的参数,第一次和前端工程师调试的时候,前端工程师并没有将参数进行escape,这样导致浏览器自己进行了escape,结果firefox和ie下分别用了utf-8编码和gbk编码,但是因为后短应用中的所有编码都是gbk的,这样firefox下发出的请求到后端Java代码中就无法正确编码。

 

解决方法:

     这个问题还是比较容易解决的,只需要前端工程师在拼装请求参数的时候用encodeURIComponent()方法对参数进行escape就可以了。

 

问题2描述:

     但是上面的解决方法只能解决部分的问题,前面注意说到后端的应用都是以GBK来处理中文的,我们在来看一下encodeURIComponent这个的说明:

 

This specifies if the encoding specified in contentType should be used for URI query parameters, instead of using the URIEncoding. This setting is present for compatibility with Tomcat 4.1.x, where the encoding specified in the contentType, or explicitly set using Request.setCharacterEncoding method was also used for the parameters from the URL. The default value is false.

 

     从上面的信息了解到这个函数只会以utf-8编码,这样到了后端用GBK编码又是乱码。

 

解决方法1:

     在看Tomcat的源代码中了解到在tomcat/jboss的connecter配置中可以配置一个:useBodyEncodingForURI,来看一下这个参数的说明:

 

This specifies if the encoding specified in contentType should be used for URI query parameters, instead of using the URIEncoding. This setting is present for compatibility with Tomcat 4.1.x, where the encoding specified in the contentType, or explicitly set using Request.setCharacterEncoding method was also used for the parameters from the URL. The default value is false.
 

     也就是说:打开这个开关以后,tomcat/jboss就会使用contentType而不是使用URIEncoding对URI请求参数进行编码,contentType可以通过调用Request.setCharacterEncoding来设置。这样你就可以在请求参数里面放一个编码方式,后端读取到以后就可以根据这个编码方式设置contentType,从而让servlet engine对URI请求参数进行正确的编码,但是如果你的servlet engine(比如jetty)并不提供这样的机制,那这个方法也就不奏效了。

 

解决方法2:

     第一个方法事实上让后端应用依赖了servletEngine,第二种方法就是让后端应用框架来做URI请求参数的编码,可以像上面一样,在请求参数里面指定URI请求参数的编码方式,后端读取到这个参数后,由应用框架去根据这个编码方式对URI请求参数进行编码。

 

原文发表于:http://www.khotyn.com/2011/02/16/yet_another_uri_encoding_problem/