IIS неправильно декодирует URL-адреса, содержащие символы вне языкового стандарта системы
Похоже, что IIS неправильно доставляет URL-адрес запроса в веб-приложение, если URL-адрес содержит символы в кодировке UTF-8, которые не поддерживаются текущим языковым стандартом системы. Все "неподдерживаемые" символы заменяются знаками вопроса ('?').
Пример: языковой стандарт системы установлен на норвежский. Следующий 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/
Приложение использует два способа обработки запросов:
- wfastcgi + Python
- ISAPI + C++
Оба страдают от одной и той же проблемы, и оба не имеют проблем, если URL содержит только символы, которые поддерживаются системным языком.
В случае с ISAPI это выглядит так EXTENSION_CONTROL_BLOCK::lpszPathInfo
уже выдает URL-адрес, декодированный в процентах, где все "неподдерживаемые" символы заменены знаками вопроса. EXTENSION_CONTROL_BLOCK::lpszPathInfo
Атрибут является многобайтовой символьной строкой, и для этой структуры не существует строковой версии с широкими символами.
Есть ли способ получить исходный URL-адрес в кодировке процента или запретить IIS декодировать URL-адреса, чтобы обойти проблему?
1 ответ
Решение для ISAPI
Получить URL запроса из серверной переменной HTTP_URL
скорее, чем PATH_INFO
, Это обеспечивает исходный URL-код в процентах, который затем можно правильно декодировать (путем процентного декодирования в массив байтов и интерпретации этого массива байтов в виде строки в кодировке UTF-8).
Эта переменная содержит строку запроса и исходный путь до перезаписи URL, что может быть нежелательным, поэтому может потребоваться дополнительная обработка.
Кроме того, для запросов обработчиков ошибок эта переменная содержит строку в формате, аналогичном
<DLL_PATH>?<STATUS_CODE>;<ORIGINAL_HTTP_URL>
который нужно разобрать. Но он содержит всю информацию, которая PATH_INFO
содержит, кроме как без неправильного декодирования.
Примечание: получение Path_INFO
с помощью GetServerVariable
, а не из EXTENSION_CONTROL_BLOCK
структура не решает проблему кодирования.
Решение для wfastcgi
Переменные сервера кодируются с использованием системного языкового стандарта (называемого 'mbcs'
в Python) по умолчанию. Это поведение можно изменить, установив раздел реестра:
reg add HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\w3svc\Parameters /v FastCGIUtf8ServerVariables /t REG_MULTI_SZ /d REQUEST_URI\0PATH_INFO
Обратите внимание, что это повлияет на все приложения wfastcgi на одном и том же сервере и может нарушить работу существующих приложений, которые не ожидают, что переменные будут кодироваться в UTF-8 (довольно маловероятно, поскольку любое нормальное приложение, использующее URL-адреса, отличные от ASCII, будет использовать кодировку UTF-8...).
Смотрите также https://support.microsoft.com/en-us/help/2277918/fix-a-php-application-that-depends-on-the-request-uri-server-variable