2012年3月22日

URL中包含"\"导致apache和tomcat不能正确处理的问题


URL中包含"\"会导致apache和tomcat无法正确处理,比如访问/a\b时:
  • apache会返回404
  • tomcat则会返回400
如果希望apache能处理包含"\"的url,则需要做如下修改: 在conf中加上AllowEncodedSlashes On即可,默认为off,参见apache docs.

而tomcat之所以会返回400,是由于org.apache.catalina.connector.CoyoteAdapter中有这么一个配置

protected static final boolean ALLOW_BACKSLASH = Boolean.valueOf(System.getProperty("org.apache.catalina.connector.CoyoteAdapter.ALLOW_BACKSLASH", "false")).booleanValue();

默认是不允许"\"的,当/a\b这个url进入tomcat的时候,CoyoteAdapter的normalize方法会返回false。 从而能导致CoyoteAdapter的service方法返回400:

// Normalization
if (!normalize(req.decodedURI())) {
    res.setStatus(400);
    res.setMessage("Invalid URI");
    connector.getService().getContainer().logAccess(request, response, 0, true);
    return false;
}

以下是normalize方法的说明:

Normalize URI. 

This method normalizes "\", "//", "/./" and "/../". This method will return false when trying to go above the root, or if the URI contains a null byte.

这是相关代码,完整实现可自行查看源码:

for (pos = start; pos < end; pos++) {
    if (b[pos] == (byte) '\\') {
        if (ALLOW_BACKSLASH) {
            b[pos] = (byte) '/';
        } else {
            return false;
        }
    }
    if (b[pos] == (byte) 0) {
        return false;
    }
}
因此,只要在tomcat启动参数中加上-Dorg.apache.catalina.connector.CoyoteAdapter.ALLOW_BACKSLASH=true就可以正常访问类似/a\b的url了。