IIS 错误地解码包含系统区域设置之外的字符的 URL

IIS incorrectly decodes URLs containing characters outside the system locale

如果 URL 包含当前系统区域设置不支持的 UTF-8 编码字符,IIS 似乎会错误地将请求 URL 传递给 Web 应用程序。所有 "unsupported" 个字符都替换为问号 ('?')。

示例:系统区域设置为挪威语。 以下 URL 工作正常:

/myapp/Blåbærsyltetøy/

以下URL不工作:

/myapp/черничный-джем/

在这两个 URL 中,非 ASCII 字符都被编码为 UTF-8,然后进行百分号编码,所以实际的 URL 看起来像这样:

/myapp/Bl%C3%A5b%C3%A6rsyltet%C3%B8y/
/myapp/%D1%87%D0%B5%D1%80%D0%BD%D0%B8%D1%87%D0%BD%D1%8B%D0%B9-%D0%B4%D0%B6%D0%B5%D0%BC/

应用程序使用两种方式处理请求:

两者都遇到同样的问题,如果 URL 仅包含系统区域设置支持的字符,则两者都没有问题。

在 ISAPI 的情况下,EXTENSION_CONTROL_BLOCK::lpszPathInfo 似乎已经提供了百分比解码的 URL,其中所有 "unsupported" 字符都已被问号替换。 EXTENSION_CONTROL_BLOCK::lpszPathInfo属性是多字节字符串,没有宽字符串版本的结构。

有没有办法获取原始的百分比编码 URL 或阻止 IIS 解码 URLs 来解决该问题?

ISAPI 解决方案

从服务器变量 HTTP_URL 而不是 PATH_INFO 获取请求 URL。这提供了原始的百分比编码 URL,然后可以正确解码(通过百分比解码为字节数组并将该字节数组解释为 UTF-8 编码的字符串)。

此变量包含查询字符串和URL重写前的原始路径,可能不需要,因此可能需要一些额外的处理。

此外,对于错误处理程序请求,此变量包含格式类似于

的字符串
<DLL_PATH>?<STATUS_CODE>;<ORIGINAL_HTTP_URL>

需要解析。但它包含 PATH_INFO 包含的所有信息,除了没有错误解码。

注意:使用 GetServerVariable 而不是从 EXTENSION_CONTROL_BLOCK 结构获取 Path_INFO 不会 解决编码问题。

wfastcgi的解决方案

服务器变量默认使用系统语言环境编码(在Python中称为'mbcs')。可以通过设置注册表项来更改此行为:

reg add HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\w3svc\Parameters /v FastCGIUtf8ServerVariables /t REG_MULTI_SZ /d REQUEST_URI[=11=]PATH_INFO

请注意,这将影响同一服务器上的所有 wfastcgi 应用程序,并且可能会破坏不希望变量采用 UTF-8 编码的现有应用程序(不太可能,因为任何使用非 ASCII 的理智应用程序 URLs 将使用 UTF-8 编码...)。

另见 https://support.microsoft.com/en-us/help/2277918/fix-a-php-application-that-depends-on-the-request-uri-server-variable