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

Другие вопросы по тегам