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.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
文件中禁止显示警告。#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
- System.Text.Encoding.UTF7
- UTF7Encoding()
- UTF7Encoding(Boolean)
- System.Text.Encoding.GetEncoding(Int32)
- System.Text.Encoding.GetEncoding(String)
- System.Text.Encoding.GetEncoding(Int32, EncoderFallback, DecoderFallback)
- System.Text.Encoding.GetEncoding(String, EncoderFallback, DecoderFallback)
- System.Text.Encoding.GetEncodings()