UTF-7 代码路径已过时

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

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

更改描述

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

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

此外,Encoding.GetEncodings() 方法枚举了一个表示 UTF-7 编码的实例,该方法还枚举了系统上注册的所有 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() 该方法不包括它返回的数组中的 EncodingInfo UTF-7 编码。 排除了编码,因为它无法实例化。

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 客户端或服务器可能会获取 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.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

    可以在代码或项目的 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