Поделиться через


Кодовые пути UTF-7 устарели

Кодировка UTF-7 больше не используется среди приложений, и многие спецификации теперь запрещают его использование в обмене. Он также иногда используется в качестве вектора атаки в приложениях, которые не ожидают возникновения данных в кодировке UTF-7. Корпорация Майкрософт предупреждает об использовании System.Text.UTF7Encoding , так как она не обеспечивает обнаружение ошибок.

Следовательно, Encoding.UTF7 свойства и UTF7Encoding конструкторы теперь устарели. Кроме того, Encoding.GetEncoding и Encoding.GetEncodings больше не позволяют вам указать UTF-7.

Описание изменения

Ранее можно создать экземпляр кодировки UTF-7 с помощью Encoding.GetEncoding API. Рассмотрим пример.

Encoding enc1 = Encoding.GetEncoding("utf-7"); // By name.
Encoding enc2 = Encoding.GetEncoding(65000); // By code page.

Кроме того, экземпляр, представляющий кодировку UTF-7, был перечислен методом Encoding.GetEncodings() , который перечисляет все Encoding экземпляры, зарегистрированные в системе.

Начиная с .NET 5, Encoding.UTF7 свойства и UTF7Encoding конструкторы устарели и создают предупреждение SYSLIB0001. Тем не менее, чтобы уменьшить количество предупреждений, которые пользователи получают при использовании UTF7Encoding класса, тип UTF7Encoding не отмечен как устаревший.

// The next line generates warning SYSLIB0001.
UTF7Encoding enc = new UTF7Encoding();
// The next line does not generate a warning.
byte[] bytes = enc.GetBytes("Hello world!");

Кроме того, Encoding.GetEncoding методы рассматривают имя utf-7 кодирования и кодовую страницу 65000 как unknown. Обработка кодировки как unknown причиняет методу вызвать исключение ArgumentException.

// Throws ArgumentException, same as calling Encoding.GetEncoding("unknown").
Encoding enc = Encoding.GetEncoding("utf-7");

Наконец, Encoding.GetEncodings() метод не включает кодировку UTF-7 в EncodingInfo массив, который он возвращает. Кодировка исключена, так как она не может быть создана.

foreach (EncodingInfo encInfo in Encoding.GetEncodings())
{
    // The next line would throw if GetEncodings included UTF-7.
    Encoding enc = Encoding.GetEncoding(encInfo.Name);
}

Причина изменения

Многие приложения вызывают Encoding.GetEncoding("encoding-name") с именем кодировки, которое предоставлено ненадежным источником. Например, веб-клиент или сервер могут принимать charset часть заголовка Content-Type и передавать значение напрямую Encoding.GetEncoding без проверки. Это может позволить вредоносной конечной точке указать Content-Type: ...; charset=utf-7, что может привести к неправильному поведению принимающего приложения.

Кроме того, отключение путей кода UTF-7 позволяет оптимизировать компиляторы, такие как те, которые используются Blazor, для удаления этих путей кода полностью из результирующего приложения. В результате скомпилированные приложения работают более эффективно и занимают меньше места на диске.

Представленная версия

5,0

В большинстве случаев вам не нужно предпринимать никаких действий. Однако для приложений, которые ранее активировали пути кода, связанные с UTF-7, рассмотрите приведенные ниже рекомендации.

  • Если ваше приложение вызывает Encoding.GetEncoding с неизвестными именами кодировки, предоставленными ненадежным источником:

    Вместо этого сравните имена кодировки с настраиваемым списком разрешений. Настраиваемый список разрешенных элементов должен содержать как минимум отраслевой стандарт "utf-8". В зависимости от клиентов и нормативных требований может потребоваться также разрешить кодирование для конкретных регионов, например "GB18030".

    Если вы не реализуете список разрешений, Encoding.GetEncoding вернется любой Encoding , встроенный в систему или зарегистрированный с помощью пользовательского EncodingProvider. Проверьте требования вашей службы, чтобы убедиться, что это нужное поведение. По умолчанию UTF-7 будет отключен, если приложение не включает переключатель совместимости, упомянутый далее в этой статье.

  • Если вы используете Encoding.UTF7 или UTF7Encoding в собственном протоколе или формате файла:

    Переключение на использование Encoding.UTF8 или UTF8Encoding. UTF-8 является отраслевым стандартом и широко поддерживается на разных языках, операционных системах и средах выполнения. Использование UTF-8 упрощает дальнейшее обслуживание кода и делает его более совместимым с остальной частью экосистемы.

  • Если вы сравниваете Encoding экземпляр с Encoding.UTF7:

    Вместо этого попробуйте выполнить проверку на общеизвестную кодовую страницу UTF-7, которая является 65000. Сравнивая страницу кодов, вы избегаете предупреждения, а также обрабатываете некоторые пограничные случаи, например, если кто-то вызвал new UTF7Encoding() или создал подкласс для типа.

    void DoSomething(Encoding enc)
    {
        // Don't perform the check this way.
        // It produces a warning and misses some edge cases.
        if (enc == Encoding.UTF7)
        {
            // Encoding is UTF-7.
        }
    
        // Instead, perform the check this way.
        if (enc != null && enc.CodePage == 65000)
        {
            // Encoding is UTF-7.
        }
    }
    
  • Если необходимо использовать Encoding.UTF7 или UTF7Encoding:

    Предупреждение можно отключить SYSLIB0001 в коде проекта или в его csproj-файле.

    #pragma warning disable SYSLIB0001 // Disable the warning.
    Encoding enc = Encoding.UTF7;
    #pragma warning restore SYSLIB0001 // Re-enable the warning.
    
    <Project Sdk="Microsoft.NET.Sdk">
      <PropertyGroup>
       <TargetFramework>net5.0</TargetFramework>
       <!-- NoWarn below suppresses SYSLIB0001 project-wide -->
       <NoWarn>$(NoWarn);SYSLIB0001</NoWarn>
      </PropertyGroup>
    </Project>
    

    Замечание

    Подавление SYSLIB0001 отключает только предупреждения об устаревании Encoding.UTF7 и UTF7Encoding. Он не отключает другие предупреждения или не изменяет поведение API, например Encoding.GetEncoding.

  • Если необходимо поддерживать Encoding.GetEncoding("utf-7", ...):

    Вы можете повторно включить поддержку этого с помощью коммутатора совместимости. Этот параметр совместимости можно указать в CSPROJ-файле приложения или в файле конфигурации среды выполнения, как показано в следующих примерах.

    В CSPROJ-файле приложения:

    <Project Sdk="Microsoft.NET.Sdk">
      <PropertyGroup>
       <TargetFramework>net5.0</TargetFramework>
       <!-- Re-enable support for UTF-7 -->
       <EnableUnsafeUTF7Encoding>true</EnableUnsafeUTF7Encoding>
      </PropertyGroup>
    </Project>
    

    В файлеruntimeconfig.template.json приложения:

    {
      "configProperties": {
        "System.Text.Encoding.EnableUnsafeUTF7Encoding": true
      }
    }
    

    Подсказка

    Если вы повторно включите поддержку UTF-7, необходимо выполнить проверку безопасности кода, который вызывает Encoding.GetEncoding.

Затронутые API