.NET Framework 4.7.2
在 .NET Framework 4.x
早期版本的基础之上构建而成,新增了许多修补程序和功能,同时很好地保持了产品的稳定性。
可以通过安装 .NET Framework 4.7.2
开发人员工具包,在 Visual Studio 2012 或更高版本中定位 .NET Framework 4.7.2
。
.NET Framework 4.7.2 中的新增功能
.NET Framework 4.7.2
在以下几个领域新增了功能:
核心
ASP.NET 2.0
网络连接
SQL
WPF
ClickOnce
.NET Framework 4.7.2
持续关注的重点是辅助功能的改进,使应用程序能为辅助技术的用户提供最佳体验。 有关 .NET Framework 4.7.2
中辅助功能改进的信息,请参阅 .NET Framework
中辅助功能的新增功能。
核心
.NET Framework 4.7.2
提供大量的加密增强功能、对 ZIP
存档更好的解压缩支持以及额外的集合 API。
RSA.Create
和 DSA.Create
的新重载
利用 DSA.Create(DSAParameters)
和 RSA.Create(RSAParameters)
方法,可在实例化新的 DSA
或 RSA
密钥时提供密钥参数。 它们允许你替换如下所示的代码:
//在.NET Framework 4.7.2之前
using (RSA rsa = RSA.Create())
{
rsa.ImportParameters(rsaParameters);
//使用RSA实例执行的其他代码
}
采用类似如下所示的代码:
//从.NET Framework 4.7.2开始
using (RSA rsa = RSA.Create(rsaParameters))
{
//使用rsa实例执行的其他代码
}
DSA.Create(Int32)
和 RSA.Create(Int32)
方法允许生成具有特定密钥大小的 DSA
或 RSA
密钥。 例如:
using (DSA dsa = DSA.Create(2048))
{
// Other code to execute using the dsa instance.
}
Rfc2898DeriveBytes
构造函数接受哈希算法名称
Rfc2898DeriveBytes
类具有三个带 HashAlgorithmName
参数的构造函数,该参数标识在派生密钥时使用的 HMAC
算法。 与 SHA-1
相比,开发人员应使用基于 SHA-2
的 HMAC
,例如 SHA-256
,如下面的示例所示:
private static byte[] DeriveKey(string password, out int iterations, out byte[] salt,
out HashAlgorithmName algorithm)
{
iterations = 100000;
algorithm = HashAlgorithmName.SHA256;
const int SaltSize = 32;
const int DerivedValueSize = 32;
using (Rfc2898DeriveBytes pbkdf2 = new Rfc2898DeriveBytes(password, SaltSize,
iterations, algorithm))
{
salt = pbkdf2.Salt;
return pbkdf2.GetBytes(DerivedValueSize);
}
}
临时密钥支持
PFX
导入可以选择绕过硬盘直接从内存加载私钥。 如果在 X509Certificate2
构造函数或 X509Certificate2.Import
方法的其中一个重载中指定了新的 X509KeyStorageFlags.EphemeralKeySet
标记,则私钥将加载为临时密钥。 这能防止密钥在磁盘上可见。 但是:
- 由于密钥不会保留到磁盘,最好不要将通过此标记加载的证书添加到
X509Store
。 - 以这种方式加载的密钥大多都是通过
Windows CNG
加载的。 因此,调用方必须通过调用扩展方法访问私钥,例如
cert.GetRSAPrivateKey()
。X509Certificate2.PrivateKey
属性不起作用。 - 由于旧的
X509Certificate2.PrivateKey
属性对证书不起作用,开发人员应在切换至临时密钥之前执行严密的测试。
PKCS#10
证书签名请求和X.509
公钥证书的编程式创建
从 .NET Framework 4.7.2
开始,工作负载可以生成证书签名请求 (CSR
),这允许将证书请求生成分阶到现有工具中。 这在测试方案中常常很有用。
有关详细信息和代码示例,请参阅 .NET 博客中的“PKCS#10 证书签名请求和 X.509 公钥证书的编程式创建
”。
新的 SignerInfo
成员
从 .NET Framework 4.7.2
开始,SignerInfo
类将公开更多有关签名的信息。 你可以检索 System.Security.Cryptography.Pkcs.SignerInfo.SignatureAlgorithm
属性的值,以确定签名者采用的签名算法。 可以调用 SignerInfo.GetSignature
来获取此签名者的加密签名副本。
在 CryptoStream
释放后保持包装流打开
从 .NET Framework 4.7.2
开始,CryptoStream
类有了一个额外的构造函数可允许 Dispose
不关闭包装流。 若要在释放 CryptoStream
实例后保持包装流的打开状态,请调用新的 CryptoStream
构造函数,如下所示:
var cStream = new CryptoStream(stream, transform, mode, leaveOpen: true);
DeflateStream
中的解压缩更改
从 .NET Framework 4.7.2
开始,DeflateStream
类中的解压缩操作的实现变为默认使用本机 Windows API
。 这样通常能大大地提高性能。
对于面向 .NET Framework 4.7.2
的应用程序,默认启用通过使用 Windows API
进行解压缩的支持。 对于面向旧版 .NET Framework
但在 .NET Framework 4.7.2
下运行的应用程序,可以将以下 AppContext
开关添加到应用程序配置文件,从而选择启用此行为:
额外的集合 API
.NET Framework 4.7.2
将一些新 API
添加到 SortedSet<T>
和 HashSet<T>
类型。 这些方法包括:
-
TryGetValue
方法,将其他集合类型中使用的尝试模式扩展到了这两种类型中。 这两个方法是:public bool HashSet.TryGetValue(T equalValue, out T actualValue)
public bool SortedSet.TryGetValue(T equalValue, out T actualValue)
-
Enumerable.To*
扩展方法,将集合转换为HashSet<T>
:public static HashSet ToHashSet(this IEnumerable source)
public static HashSet ToHashSet(this IEnumerable source, IEqualityComparer comparer)
-
新的
HashSet<T>
构造函数,让你设置集合容量,可以在提前知道HashSet<T>
大小的情况下提升性能:public HashSet(int capacity)
public HashSet(int capacity, IEqualityComparer comparer)
ConcurrentDictionary<TKey,TValue>
类包含 AddOrUpdate
和 GetOrAdd
方法的新重载,以便在词典中检索值或添加找不到的值,以及将值添加到词典或者更新已存在的值。
public TValue AddOrUpdate<TArg>(TKey key, Func<TKey, TArg, TValue> addValueFactory, Func<TKey, TValue, TArg, TValue> updateValueFactory, TArg factoryArgument)
public TValue GetOrAdd<TArg>(TKey key, Func<TKey, TArg, TValue> valueFactory, TArg factoryArgument)
Web 窗体中的依赖项注入支持
依赖项注入 (DI) 分离对象和它们的依赖项,使得对象的代码不再仅因依赖项更改而需要进行更改。 在开发面向 .NET Framework 4.7.2
的 ASP.NET
应用程序时,可以:
- 在处理程序和模块、页面实例和 ASP.NET Web 应用程序项目的用户控件中使用基于资源库、基于接口和基于构造函数的注入。
- 在处理程序和模块、页面实例和 ASP.NET 网站项目的用户控件中使用基于资源库和基于接口的注入。
- 插入不同的依赖关系注入框架。
同站点 cookie
支持
SameSite
防止浏览器将 cookie
和跨站点请求一起发送。 .NET Framework 4.7.2
添加了一个值为 System.Web.SameSiteMode
枚举成员的 HttpCookie.SameSite
属性。 如果它的值为 SameSiteMode.Strict
或 SameSiteMode.Lax
,ASP.NET 将 SameSite
属性添加到 set-cookie
标头。 SameSite
支持适用于 HttpCookie
对象,以及 FormsAuthentication
和 System.Web.SessionState cookie
。
可以为 HttpCookie
对象设置 SameSite
,如下所示:
var c = new HttpCookie("secureCookie", "same origin");
c.SameSite = SameSiteMode.Lax;
还可以通过修改 web.config
文件,在应用程序级别配置 SameSite cookie
:
<system.web>
<httpCookies sameSite="Strict" />
</system.web>
通过修改 Web
配置文件,可以为 FormsAuthentication
和 System.Web.SessionState cookie
添加 SameSite
:
<system.web>
<authentication mode="Forms">
<forms cookieSameSite="Lax">
<!-- ... -->
</forms>
<authentication />
<sessionSate cookieSameSite="Lax"></sessionState>
</system.web>
网络
HttpClientHandler
属性的实现
.NET Framework 4.7.1
将八个属性添加到了 System.Net.Http.HttpClientHandler
类。 不过其中有两个会引发 PlatformNotSupportedException
。 .NET Framework 4.7.2
现在为这些属性提供实现。 这些属性为:
- CheckCertificateRevocationList
- SslProtocols
SQLClient
对 Azure Active Directory
通用身份验证和多重身份验证的支持
不断增加的符合性和安全性需求让很多客户需要使用多重身份验证 (MFA)。 此外,当前的最佳做法不鼓励在连接字符串中直接包含用户密码。 为了支持这些更改,.NET Framework 4.7.2
通过添加新值“Active Directory Interactive
”扩展了 SQLClient 连接字符串,让现有“身份验证”关键字支持 MFA 和 Azure AD 身份验证。 新的交互式方法支持本机和联合 Azure AD 用户以及 Azure AD
来宾用户。 使用此方法时,SQL 数据库将支持由 Azure AD
施加的 MFA
身份验证。 此外,为了遵循安全最佳做法,身份验证流程会请求用户密码。
在以前版本的 .NET Framework
中,SQL 连接只支持 SqlAuthenticationMethod.ActiveDirectoryPassword
和 SqlAuthenticationMethod.ActiveDirectoryIntegrated
选项。 两者都是非交互式 ADAL
协议的一部分,而该协议不支持 MFA
。 利用新的 SqlAuthenticationMethod.ActiveDirectoryInteractive
选项,SQL
连接可支持 MFA
以及现有身份验证方法(密码和集成身份验证),让用户可以交互式地输入用户密码,而无需将密码存留在连接字符串中。
有关详细信息和示例,请参阅 .NET 博客中的“SQL - Azure AD 通用和多重身份验证支持”。
Always Encrypted
版本 2 的支持
NET Framework 4.7.2
为基于 enclave
的 Always Encrypted
添加支持。 Always Encrypted
的原始版本是客户端加密技术,其中的加密密钥不会离开客户端。 在基于 enclave
的 Always Encrypted
中,客户端可以选择将加密密钥发送到安全的 enclave,即一个安全的计算实体,该实体可以看作是 SQL Server
的一部分,但 SQL Server
代码无法对其进行篡改。 为了支持基于 enclave
的 Always Encrypted
,NET Framework 4.7.2
将以下类型和成员添加到 System.Data.SqlClient
命名空间:
SqlConnectionStringBuilder.EnclaveAttestationUrl
,为基于enclave
的Always Encrypted
指定 URI。SqlColumnEncryptionEnclaveProvider
,一个抽象类,所有enclave
提供程序都自它派生。SqlEnclaveSession
,封装给定enclave
会话的状态。SqlEnclaveAttestationParameters
,提供 SQL Server 所使用的认证参数,以获取执行特定认证协议所需的信息。
抽象 System.Data.SqlClient.SqlColumnEncryptionEnclaveProvider
类提供了 enclave
提供程序的功能,应用程序配置文件随后会指定该类的具体实现。 例如:
<configuration>
<configSections>
<section name="SqlColumnEncryptionEnclaveProviders" type="System.Data.SqlClient.SqlColumnEncryptionEnclaveProviderConfigurationSection,System.Data,Version=4.0.0.0,Culture=neutral,PublicKeyToken=b77a5c561934e089"/>
</configSections>
<SqlColumnEncryptionEnclaveProviders>
<providers>
<add name="Azure" type="Microsoft.SqlServer.Management.AlwaysEncrypted.AzureEnclaveProvider,MyApp"/>
<add name="HGS" type="Microsoft.SqlServer.Management.AlwaysEncrypted.HGSEnclaveProvider,MyApp" />
</providers>
</SqlColumnEncryptionEnclaveProviders >
</configuration>
基于 enclave
的 Always Encrypted
的基本流是:
- 用户创建与 SQL Server(支持基于 enclave 的
Always Encrypted
)的AlwaysEncrypted
连接。 驱动程序联系认证服务以确保它连接到正确的 enclave。 - enclave 验证成功后,驱动程序将建立与托管在 SQL Server 上的安全 enclave 之间的安全信道。
- 在 SQL 连接期间,驱动程序与安全
enclave
共享由客户端授权的加密密钥。
Windows Presentation Foundation
按源查找 ResourceDictionaries
从 .NET Framework 4.7.2
开始,诊断助手可以找到从给定源 URI 创建的 ResourceDictionaries
。 (此功能通过诊断助手使用,而非生产应用程序。)诊断助手(例如 Visual Studio 的“编辑并继续”)让用户可以编辑 ResourceDictionary
以将更改应用到正在运行的应用程序。 要实现这一点,其中一个步骤是从被编辑的字典中找到正在运行的应用程序创建的所有 ResourceDictionaries
。 例如,应用程序可以声明某个从给定源 URI 复制内容的 ResourceDictionary
:
<ResourceDictionary Source="MyRD.xaml">
编辑 MyRD.xaml
中的原始标记的诊断助手可以使用新功能来找到字典。 此功能通过新的静态方法 ResourceDictionaryDiagnostics.GetResourceDictionariesForSource
实现。 诊断助手使用标识原始标记的绝对 URI
调用新方法,如以下代码所示:
IEnumerable<ResourceDictionary> dictionaries = ResourceDictionaryDiagnostics.GetResourceDictionariesForSource(new Uri("pack://application:,,,/MyApp;component/MyRD.xaml"));
该方法返回空的枚举值,除非启用了 VisualDiagnostics
并且设置了 ENABLE_XAML_DIAGNOSTICS_SOURCE_INFO
环境变量。
查找 ResourceDictionary
所有者
从 .NET Framework 4.7.2
开始,诊断助手可以找到给定 ResourceDictionary
的所有者。 (此功能供诊断助手,而非生产应用程序使用。)每当对 ResourceDictionary
做出更改时,WPF 会自动查找所有可能会受此更改影响的 DynamicResource
引用。
诊断助手(例如 Visual Studio 的“编辑并继续”)可能想对此进行扩展以处理 StaticResource
引用。 此过程的第一步是找到字典的所有者,也就是找到其 Resources
属性引用该字典(不管是直接引用,还是通过 ResourceDictionary.MergedDictionaries
属性间接引用)的所有对象。 System.Windows.Diagnostics.ResourceDictionaryDiagnostics
类上实现的三个新的静态方法(每个对应具有 Resources
属性的基类型)支持此步骤:
public static IEnumerable<FrameworkElement> GetFrameworkElementOwners(ResourceDictionary dictionary);
public static IEnumerable<FrameworkContentElement> GetFrameworkContentElementOwners(ResourceDictionary dictionary);
public static IEnumerable<Application> GetApplicationOwners(ResourceDictionary dictionary);
这些方法返回空的枚举值,除非启用了 VisualDiagnostics
并且设置了 ENABLE_XAML_DIAGNOSTICS_SOURCE_INFO
环境变量。
查找 StaticResource
引用
现在,每当一个 StaticResource
引用被解析时,诊断助手都能收到通知。 (此功能供诊断助手,而非生产应用程序使用。)诊断助手(例如 Visual Studio 的“编辑并继续”)可能想在 ResourceDictionary
中某个资源的值发生更改时更新该资源的所有使用。 WPF 为 DynamicResource
引用自动完成此操作,但不会为 StaticResource
引用有意执行该操作。 从 .NET Framework 4.7.2 开始
,诊断助手可以利用这些通知来查找静态资源的使用情况。
该通知由新的 ResourceDictionaryDiagnostics.StaticResourceResolved
事件实现:
public static event EventHandler<StaticResourceResolvedEventArgs> StaticResourceResolved;
每当运行时解析 StaticResource
引用时,都会引发此事件。 StaticResourceResolvedEventArgs
参数描述解析,并指示托管 StaticResource
引用的对象和属性及用于解析的 ResourceDictionary
和密钥:
public class StaticResourceResolvedEventArgs : EventArgs
{
public Object TargetObject { get; }
public Object TargetProperty { get; }
public ResourceDictionary ResourceDictionary { get; }
public object ResourceKey { get; }
}
除非启用 VisualDiagnostics
并设置了 ENABLE_XAML_DIAGNOSTICS_SOURCE_INFO
环境变量,否则不会引发该事件(且忽略它的 add
访问器)。
ClickOnce
Windows 窗体的 HDPI 感知应用程序、Windows Presentation Foundation (WPF) 以及 Visual Studio Tools for Office (VSTO) 都可以通过使用 ClickOnce
进行部署。 如果在应用程序清单中找到了以下条目,则部署将在 .NET Framework 4.7.2
下成功执行:
<windowsSettings>
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
</windowsSettings>
对于 Windows 窗体应用程序,不需要像以前那样在应用程序配置文件(而非应用程序清单)中设置 DPI 感知就可以成功完成 ClickOnce
部署。
.NET Framework 4.7.1
中的新增功能
.NET Framework 4.7.1
在以下几个领域新增了功能:
核心
公共语言运行时 (CLR)
网络连接
ASP.NET 2.0
此外,.NET Framework 4.7.1
的重点是改进了辅助功能,使应用程序能为辅助技术的用户提供最佳体验。 有关 .NET Framework 4.7.1
中辅助功能改进的信息,请参阅 .NET Framework
中辅助功能的新增功能。
核心
支持 .NET Standard 2.0
.NET Standard
定义一组 API,这些 API 必须可用于支持 Standard
版本的每个 .NET 实现。 .NET Framework 4.7.1
完全支持 .NET Standard 2.0
并增加了 200 个 API,这些 API 在 .NET Standard 2.0
中定义,.NET Framework 4.6.1、4.6.2
和 4.7
中也延续使用。 (请注意,这些版本的 .NET Framework
只有在其他 .NET Standard
支持文件也部署在目标系统时才支持 .NET Standard 2.0
。)有关详细信息,请参阅 .NET Framework 4.7.1 Runtime and Compiler Features
(.NET Framework 4.7.1 运行时和编译器功能)博客文章中的“BCL - .NET Standard 2.0 Support
”(BCL - .NET Standard 2.0 支持)。
支持配置生成器
配置生成器允许开发者在运行时动态地插入和生成应用程序的配置设置。 自定义配置生成器可用于修改配置节中的现有数据,也可用于生成全新的配置节。 如果没有配置生成器,.config
文件将是静态的,并且其设置将在应用程序启动之前定义。
若要创建自定义配置生成器,请从抽象的 ConfigurationBuilder
类派生生成器并且替代其 ConfigurationBuilder.ProcessConfigurationSection
和 ConfigurationBuilder.ProcessRawXml
。 也可在 .config
文件中定义生成器。 有关详细信息,请参阅 .NET Framework 4.7.1 ASP.NET and Configuration Features
(.NET Framework 4.7.1 ASP.NET 和配置功能)博客文章中的“Configuration Builders
”(配置生成器)一节。
运行时功能检测
System.Runtime.CompilerServices.RuntimeFeature
类提供一种机制,用于确定给定的 .NET 实现在编译时或运行时是否支持预定义的功能。 在编译时,编译器可以检查指定的字段是否存在,以确定是否支持某项功能,如果支持,它会发出利用这一功能的代码。 在运行时,应用程序可以在运行时发出代码之前调用 RuntimeFeature.IsSupported
方法。 有关详细信息,请参阅 Add helper method to describe features supported by the runtime
(添加 helper 方法以描述运行时支持的功能)。
值元组类型是可序列化的
从 .NET Framework 4.7.1
起,System.ValueTuple
及其相关的泛型类型被标记为可序列化,允许进行二进制序列化。 这样,可以更轻松地将元组类型(如 Tuple<T1,T2,T3>
和 Tuple<T1,T2,T3,T4>
)迁移到值元组类型。 有关详细信息,请参阅 .NET Framework 4.7.1 Runtime and Compiler Features
(.NET Framework 4.7.1 运行时和编译器功能)博客文章中的“Compiler – ValueTuple is Serializable”(编译器 – 值元组是可序列化的)。
支持只读引用
.NET Framework 4.7.1
增加了 System.Runtime.CompilerServices.IsReadOnlyAttribute
。 此特性由语言编译器用于标记具有只读 ref 返回类型或参数的成员。 有关详细信息,请参阅 .NET Framework 4.7.1 Runtime and Compiler Features
(.NET Framework 4.7.1 运行时和编译器功能)博客文章中的“Compiler -- Support for ReadOnlyReferences
”(编译器 – 支持只读引用)。 有关 ref
返回值的信息,请参阅 ref
返回值和 ref
局部变量(C# 指南)和 ref
返回值 (Visual Basic)。
公共语言运行时 (CLR)
垃圾回收性能改进
.NET Framework 4.7.1
中的垃圾回收 (GC
) 的更改提升了整体性能,尤其是大型对象堆 (LOH
) 分配的性能。 在 .NET Framework 4.7.1
中,小型对象堆 (SOH
) 分配和 LOH
分配使用不同的锁,当后台 GC (BGC
) 整理 SOH
时即发生 LOH
分配。 这样,进行大量 LOH
分配的应用程序发生分配锁争用的情况将减少,从而提高性能。 有关详细信息,请参阅 .NET Framework 4.7.1 Runtime and Compiler Features
(.NET Framework 4.7.1 运行时和编译器功能)博客文章中的“Runtime -- GC Performance Improvements
”(运行时 – GC 性能改进)一节。
网络
Message.HashAlgorithm
的 SHA-2
支持
在 .NET Framework 4.7
及早期版本中,Message.HashAlgorithm
属性仅支持 HashAlgorithm.Md5
和 HashAlgorithm.Sha
的值。 从 .NET Framework 4.7.1 开始,还支持 HashAlgorithm.Sha256
、HashAlgorithm.Sha384
和 HashAlgorithm.Sha512
。 实际是否使用此值取决于消息队列,因为 Message
实例本身不进行哈希处理,而是简单地将值传递到消息队列。 有关详细信息,请参阅 .NET Framework 4.7.1 ASP.NET and Configuration Features
(.NET Framework 4.7.1 ASP.NET 和配置功能)博客文章中的“SHA-2 support for Message.HashAlgorithm”(Message.HashAlgorithm 的 SHA-2 支持)一节。
ASP.NET
ASP.NET 应用程序中的执行步骤
ASP.NET
处理包括 23 个事件的预定义管道中的请求。 ASP.NET 执行每个事件处理程序作为一个执行步骤。 对于 .NET Framework 4.7
之前的 ASP.NET 版本,由于本机和托管线程之间的切换,ASP.NET 无法传送执行上下文。 ASP.NET 有选择性地仅传送 HttpContext
。 从 .NET Framework 4.7.1
开始,HttpApplication.OnExecuteRequestStep(Action<HttpContextBase,Action>)
方法还允许模块还原环境数据。 此功能针对与跟踪、分析、诊断或事务(例如应用程序的执行流)相关的库。 有关详细信息,请参阅 .NET Framework 4.7.1 ASP.NET and Configuration Features
(.NET Framework 4.7.1 ASP.NET 和配置功能)博客文章的“ASP.NET Execution Step Feature”(ASP.NET 执行步骤功能)一节。
ASP.NET HttpCookie
分析
.NET Framework 4.7.1 包括新的方法 HttpCookie.TryParse
,此方法提供标准化的方式来从字符串创建 HttpCookie
对象,并精确分配 cookie
值(如过期日期和路径)。 有关详细信息,请参阅 .NET Framework 4.7.1 ASP.NET and Configuration Features
(.NET Framework 4.7.1 ASP.NET 和配置功能)博客文章中的“ASP.NET HttpCookie parsing”(ASP.NET HttpCookie 分析)一节。
ASP.NET 窗体身份验证凭据的 SHA-2 哈希选项
在 .NET Framework 4.7
及其早期版本中,ASP.NET 允许开发者使用 MD5 或 SHA1 在配置文件中存储用户凭据和哈希密码。 从 .NET Framework 4.7.1 开始,ASP.NET 还支持新的安全 SHA-2
哈希选项(如 SHA256、SHA384 和 SHA512)。 SHA1
保留默认值,非默认哈希算法可以在 Web 配置文件中定义。 例如:
XML
<system.web>
<authentication mode="Forms">
<forms loginUrl="~/login.aspx">
<credentials passwordFormat="SHA512">
<user name="jdoe" password="6D003E98EA1C7F04ABF8FCB375388907B7F3EE06F278DB966BE960E7CBBD103DF30CA6D61F7E7FD981B2E4E3A64D43C836A4BEDCA165C33B163E6BCDC538A664" />
</credentials>
</forms>
</authentication>
</system.web>