【发布时间】:2010-10-27 14:14:23
【问题描述】:
使用场景
我们已经实现了一个网络服务,我们的网络前端开发人员在内部使用(通过 php api)来显示产品数据。在网站上,用户输入一些东西(即查询字符串)。在内部,网站通过 api 调用服务。
注意:我们使用的是restlet,而不是tomcat
原来的问题
Firefox 3.0.10 似乎尊重浏览器中选择的编码,并根据选择的编码对 url 进行编码。这确实会导致 ISO-8859-1 和 UTF-8 的查询字符串不同。
我们的网站转发来自用户的输入并且不转换它(它应该),因此它可以通过使用包含德语变音符号的查询字符串调用 web 服务的 api 来调用服务。
即对于看起来像
的查询部分 ...v=abcädef
如果选择“ISO-8859-1”,则发送的查询部分如下所示
...v=abc%E4def
但如果选择“UTF-8”,则发送的查询部分看起来像
...v=abc%C3%A4def
所需的解决方案
当我们控制服务时,因为我们已经实现了它,所以我们想在服务器端检查调用是否包含非 utf-8 字符,如果是,则以 4xx http 状态响应
详细的当前解决方案
检查每个字符 ( == string.substring(i,i+1) )
- 如果 character.getBytes()[0] 为 '?' 等于 63
- 如果 Character.getType(character.charAt(0)) 返回 OTHER_SYMBOL
代码
protected List< String > getNonUnicodeCharacters( String s ) {
final List< String > result = new ArrayList< String >();
for ( int i = 0 , n = s.length() ; i < n ; i++ ) {
final String character = s.substring( i , i + 1 );
final boolean isOtherSymbol =
( int ) Character.OTHER_SYMBOL
== Character.getType( character.charAt( 0 ) );
final boolean isNonUnicode = isOtherSymbol
&& character.getBytes()[ 0 ] == ( byte ) 63;
if ( isNonUnicode )
result.add( character );
}
return result;
}
问题
这会捕获所有无效(非 utf 编码)字符吗? 你们有没有更好(更简单)的解决方案?
注意:我用以下代码检查了 URLDecoder
final String[] test = new String[]{
"v=abc%E4def",
"v=abc%C3%A4def"
};
for ( int i = 0 , n = test.length ; i < n ; i++ ) {
System.out.println( java.net.URLDecoder.decode(test[i],"UTF-8") );
System.out.println( java.net.URLDecoder.decode(test[i],"ISO-8859-1") );
}
打印出来:
v=abc?def
v=abcädef
v=abcädef
v=abcädef
它确实不会抛出 IllegalArgumentException sigh
【问题讨论】:
标签: java string unicode encoding