使用场景
我们实现了一个 web 服务,我们的网站前端开发人员通过 php api 内部使用它来显示产品数据。在网站上,用户输入某些内容(即查询字符串)。在内部,网站通过 api 调用服务来执行操作。
注意:我们使用 restlet,而不是 tomcat
原始问题
Firefox 3.0.10 看起来会遵循浏览器中选择的编码格式并根据所选的编码格式对 url 进行编码。这会导致 ISO-8859-1 和 UTF-8 的查询字符串不同。
我们的网站将用户输入转发到服务,但不进行转换(应该转换),因此可能通过调用包含德语元音字母的查询字符串的 api 来调用 web 服务。
例如,查询部分可能如下所示:
...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 异常 叹气