UTF-7 代码路径已过时

UTF-7 编码在应用程序中不再广泛使用,并且许多规范现在在交换中禁止其使用。 它偶尔还会在不期望遇到 UTF-7 编码数据的应用程序中用作攻击途径。 Microsoft 警告不要使用 System.Text.UTF7Encoding,因为它不提供错误检测。

因此,Encoding.UTF7 属性和 UTF7Encoding 构造函数现已过时。 此外,Encoding.GetEncodingEncoding.GetEncodings 不再允许你指定 UTF-7

更改描述

以前,你可以使用 Encoding.GetEncoding API 创建 UTF-7 编码的实例。 例如:

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")。 例如,Web 客户端或服务器可能采用 Content-Type 标头的 charset 部分,并且不进行验证将值直接传递给 Encoding.GetEncoding。 这可能会使恶意终结点指定 Content-Type: ...; charset=utf-7,而这可能会导致接收应用程序出现异常行为。

此外,禁用 UTF-7 代码路径可以优化编译器(如 Blazor 使用的编译器),以便从生成的应用程序中完全删除这些代码路径。 因此,已编译的应用程序会更有效地运行,且占用更少的磁盘空间。

引入的版本

5.0

在大多数情况下,你不必执行任何操作。 但是,对于以前激活了与 UTF-7 相关的代码路径的应用,请考虑下面的指南。

  • 如果你的应用使用不受信任的源提供的未知编码名称调用 Encoding.GetEncoding

    请改为将编码名称与可配置的允许列表进行比较。 可配置的允许列表至少应包含行业标准的“utf-8”。 根据你的客户端和法规要求,你可能还需要允许特定于区域的编码,如“GB18030”。

    如果未执行允许列表,Encoding.GetEncoding 将返回内置于系统中或通过自定义 EncodingProvider 注册的任何 Encoding。 审核你服务的要求以验证这是否是所需的行为。 除非你的应用程序重新启用本文后面所述的兼容性开关,否则默认情况下将继续禁用 UTF-7。

  • 如果在你自己的协议或文件格式中使用的是 Encoding.UTF7UTF7Encoding

    切换到使用 Encoding.UTF8UTF8Encoding。 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.UTF7UTF7Encoding

    可以在代码中或在项目的 .csproj 文件中禁止显示 SYSLIB0001 警告。

    #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.UTF7UTF7Encoding 过时警告。 不会禁用任何其他警告,也不会更改 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