使用特定于平台的网络功能

已完成

HttpClient 类提供与网络的连接的抽象。 使用此类的应用独立于本机平台网络堆栈。 .NET MAUI 模板将 HttpClient 类映射到利用每个平台的本机网络堆栈的代码。 这使应用程序能够利用特定于平台的网络配置和优化功能。 当需要配置客户端应用程序以安全地连接到 REST Web 服务时,这一点尤其重要。

在本单元中,你将学习如何配置 HTTP 客户端应用程序,以使用基础平台提供的网络保护功能。

在 iOS 上配置应用传输安全性

应用传输安全性 (ATS) 是一项 iOS 功能,要求通过本机 HTTP 网络堆栈完成的每次网络通信都使用 TLS 1.2 或更高版本。 如果其中一个长期密钥泄露,现代加密算法不会泄露信息。

如果应用不遵守这些规则,则无法访问网络。 可通过两个选项解决此问题:可以更改终结点以遵守应用传输安全性策略,也可以选择退出应用传输安全性。

若选择退出应用传输安全性,请将名为 NSAppTransportSecurity 的新密钥添加到 Info.plist 文件。 在解决方案资源管理器中,在项目的 Platforms 文件夹的 iOS 文件夹中将找到 Info.plist 文件。 此密钥实际上是一个字典。 在这个字典中添加另一个名为 NSExceptionDomains 的密钥。 此密钥包含想要将其作为目标的每个终结点的子级。 每个终结点都可以有自己的配置,可指定允许或禁止哪些功能。 可以通过以下方法来添加此密钥:使用 Visual Studio 中的泛型 plist 编辑器,或将此密钥作为 XML 文件打开。

Screenshot of left context menu with the open menu item selected. On the right is the window Visual Studio, X M L (text) editor is highlighted.

下面是以 XML 格式显示的终结点的配置示例:

<key>NSAppTransportSecurity</key>
<dict>
   <key>NSExceptionDomains</key>
      <dict>
      <key>dotnet.microsoft.com</key>
      <dict>
        <key>NSExceptionMinimumTLSVersion</key>
        <string>TLSv1.0</string>
        <key>NSExceptionAllowsInsecureHTTPLoads</key>
        <true/>
      </dict>
   </dict>
</dict>

此示例向 dotnet.microsoft.com 中的终结点添加了一个异常。 如果要在开发计算机上本地调试服务,则可以使用 NSAllowsLocalNetworking 密钥选择退出应用传输安全性,以使用本地流量,如下所示:

<key>NSAppTransportSecurity</key>    
<dict>
    <key>NSAllowsLocalNetworking</key>
    <true/>
</dict>

如果无法识别所有终结点,请使用 NSAllowsArbitraryLoads 密钥禁用所有未指定终结点的应用传输安全性:

<key>NSAppTransportSecurity</key>
<dict>
   <key>NSAllowsArbitraryLoads</key>
   <true/>
</dict>

可以添加其他相关选项,以便更具体地说明想要选择退出的方式。进一步的指导超出了本模块的范畴。

配置 Android 网络安全

和 iOS 一样,Android 具有类似的网络通信安全模型。 此模型是随 Android 9(API 级别 28)一起引入的。 当应用程序以 Android 9(API 级别 28)或更高版本为目标时,明文(非 HTTPS)流量默认处于禁用状态。 如果应用需要在没有配置 HTTPS 的服务器上下载图像或文件,那么此策略可能会影响你的开发周期。 此外,你可能只是尝试在本地调试应用程序,而不希望安装开发证书。 你可能有强烈的业务需求,即所有 Android 版本上的所有 Web 流量都必须是 HTTPS。 Android 的网络安全配置功能使你能够微调应用中的网络流量安全性。

允许明文流量

要允许明文流量,请在名为 network_security_config.xml资源/xml 文件夹中创建新的 XML 文件(可能还需要创建 xml 文件夹)。 Resources 文件夹位于解决方案资源管理器的 Android 平台文件夹中。 在此文件中,添加包含 domain-config 子元素的 network-security-config 元素。 以下配置启用了流向特定域和 IP 地址的明文流量:

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
  <domain-config cleartextTrafficPermitted="true">
    <domain includeSubdomains="true">10.0.2.2</domain> <!-- Debug port -->
    <domain includeSubdomains="true">microsoft.com</domain>
  </domain-config>
</network-security-config>

无论目标框架如何,都可以在所有版本的 Android 上限制明文流量,从而增强应用的安全性。 通过将 domain-config 元素的 cleartextTrafficPermitted 属性设置为 false 可以实现。 此配置设置阻止所有非 HTTPS 流量。

若要使应用识别 network_security_config.xml 文件,请在位于“属性”文件夹中的 AndroidManifest.xml 中为 application 节点配置 networkSecurityConfig 属性:

<?xml version="1.0" encoding="utf-8"?>
<manifest>
    <application android:networkSecurityConfig="@xml/network_security_config" ...></application>
</manifest>

如果需要更具体地说明如何选择退出传输安全性,可以指定其他选项。

在本地调试应用

使用 Visual Studio 构建移动应用程序的一个重要好处是,能够使用 iOS 模拟器或 Android 模拟器运行和调试移动应用程序。 这些应用可以使用 ASP.NET Core Web 服务,这些服务在本地运行并通过 HTTP 公开。

在 iOS 模拟器中运行的应用程序可以使用计算机 IP 地址或通过 localhost 主机名连接到本地 HTTP Web 服务。 应用程序必须选择退出 ATS,以指定 NSAllowsLocalNetworking 的最小值。 例如,对于通过 /api/todoitems/ 相对 URI 公开 GET 操作的本地 HTTP Web 服务,在 iOS 模拟器中运行的应用程序可以通过向 http://localhost:<port>/api/todoitems/ 发送 GET 请求来使用操作。

在 Android 模拟器中运行的应用程序可以通过 10.0.2.2 地址连接到本地 HTTP Web 服务。 此地址是主机环回接口的别名(在开发计算机上为 127.0.0.1)。 还必须为此特定的 IP 地址设置网络安全配置。 例如,对于通过 /api/todoitems/ 相对URI公开 GET 操作的本地 HTTP 网络服务,在 Android 模拟器中运行的应用程序可以通过向 http://10.0.2.2:/api/todoitems/ 发送 GET 请求来使用该操作。

注意

在本地主机上测试运行的 ASP.NET Core Web 服务必须通过在 Startup.cs 文件中注释掉语句 app.UseHttpsRedirection(); 来禁用 HTTPS 重定向。

检测操作系统

应用可以使用 DeviceInfo 类确定它在哪个平台上运行。 在下面的示例中,应用程序根据 BaseAddress 变量是否在 Android 上运行,将此变量设置为不同的值:

public static string BaseAddress = DeviceInfo.Platform == DevicePlatform.Android ? "http://10.0.2.2:5000" : "http://localhost:5000";
public static string TodoItemsUrl = $"{BaseAddress}/api/todoitems/";