IIS错误地解码了包含系统区域外部字符的URL
如果URL包含UTF-8编码字符(它不受当前系统区域设置支持),IIS似乎错误地将请求URL传送到Web应用程序。所有“不支持”的字符都被问号('?')取代。IIS错误地解码了包含系统区域外部字符的URL
示例:系统语言环境设置为挪威语。 以下网址工作正常:
/myapp/Blåbærsyltetøy/
以下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/
该应用程序使用处理请求的方法有两种:
- wfastcgi + Python的
- ISAPI + C++
两者都来自同一个问题的痛苦,都没有问题,如果URL仅包含由系统语言环境支持的字符。
在ISAPI的情况下,看起来EXTENSION_CONTROL_BLOCK::lpszPathInfo
已经提供百分比解码的URL,其中所有“不支持”的字符已被问号替换。 EXTENSION_CONTROL_BLOCK::lpszPathInfo
属性是一个多字节字符串,并且没有该结构的宽字符字符串版本。
有没有办法获得原始的百分比编码的URL或防止IIS解码URL来解决问题?
解决方案ISAPI
从服务器变量HTTP_URL
而非PATH_INFO
获得请求的URL。这提供了原始的百分比编码的URL,然后可以正确解码(通过百分比解码为字节数组并将该字节数组解释为UTF-8编码的字符串)。
此变量包含查询字符串和URL重写之前的原始路径,这可能是不需要的,因此可能需要一些额外的处理。
此外,用于错误处理程序的请求,此变量包含以类似于
<DLL_PATH>?<STATUS_CODE>;<ORIGINAL_HTTP_URL>
的格式,其需要被解析的字符串。但它包含所有PATH_INFO
包含的信息,除非没有错误的解码。
注:获得Path_INFO
使用GetServerVariable
,而不是从EXTENSION_CONTROL_BLOCK
结构并没有解决的编码问题。
解决方案wfastcgi
服务器变量所使用的系统区域设置(在Python称为'mbcs'
)默认编码。这种行为可以通过设置注册表项进行更改:
reg add HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\w3svc\Parameters /v FastCGIUtf8ServerVariables /t REG_MULTI_SZ /d REQUEST_URI\0PATH_INFO
注意,这会影响到同一台服务器上的所有wfastcgi应用和可能会破坏不希望变量是现有的应用程序UTF-8编码的(而不可能,因为任何使用非ASCII URL的理智应用程序都会使用UTF-8编码...)。
请参见ISAPI,解决的办法是从服务器变量'HTTP_URL'获取URL,而不是'PATH_INFO'。这提供了原始的百分比编码的URL,然后可以正确解码。在wfastcgi脚本中,“HTTP_URL”不可用,并且尝试在Python中访问它会导致“KeyError”。 –
为wfastcgi尝试了此变通办法:https://support.microsoft.com/zh-cn/help/2277918/fix-a-php-application-that-depends-on-the-request-uri-server-variable - 结果:网址不再包含问号。相反,它们包含百分比编码的字节,在解释为UTF-8时会变成乱码。 –
更正我以前的评论:此处描述的修补程序和注册表变量https://support.microsoft.com/en-us/help/2277918/fix-a-php-application-that-depends-on-the-request- uri-server-variable实际上解决了wfastcgi的问题。 –